Select when in a loop, select single, shows multiple selected - ember.js

When Ember.select is used in a {{#each}}, if I select option in one select, it shows as if it is selected in all the other selects. Below is the code and screen shots.
Code in template :
{{#each feed in model.feeddefinitions}}
{{#if isEditing}}
<td> {{view Ember.Select
content=model.sections
optionValuePath="content.id"
optionLabelPath="content.name"
prompt="Select Section"
value=selectedSection}}</td>
<td>
<button class="btn btn-primary btn-sm" {{action 'add_section_to_feed' model feed.id}}>Add</button>
</td>
{{/if}}
</tr>
{{/each}}

You are experiencing this issue because selectedSection's context is not an individual feed.
If every feed has a 'selectedSection' attribute, you can give 'value=feed.selectedSection'
Or else, you have to define an itemController for an individual feed and define the selectedSection property in it.

The problem is that all your Ember.Selects are sharing a single controller and all of them are bound to the same property in the same controller value=selectedSection.
What you need to do is have a separate controller for each Ember.Select. You need a new controller for each item, for this purpose you can use the render helper.
Example: http://emberjs.jsbin.com/xahevi/1/edit?html,js,console,output

All of your selects are bound onto the same property.
You either need to bind the value/selection onto a model property or onto a controller property for each item. You can have the each helper wrap each model in a controller as follows:
{{#each feed in model.feeddefinitions itemController='feed-definition'}}
...
{{/each}}

Basically what you have to do is -
declare item controller as {{#each itemController=DesignPhotoController}} while looping.
so that each individual object will have a separate controller.
And add
selectedSection: null,
in DesignPhotoController and access it via this.get("selectedSection") in the controller.
Here is the - FIDDLE

Related

Nested each and if with Handlebars and EmberJS

I have two list of models which have relations.
A has many B
I loop through B with {{#each}} and generate a <table> with it and every row has a <select> where all As, that exist, are listed.
If an B belongs to an A it should be selected in the <select>
Example:
<table>
{{#each b in listofb}}
<tr><td>
<select>
{{#each a in listofa}}
{{#if b belongsto a}}
<option selected>a.someAttribute</option>
{{else}}
<option>a.someAttribute</option>
{{/if}}
{{/each}}
</select>
</td></tr>
{{/each}}
</table>
There is probably a way to do this with handlebar-helpers, but I don't know if I can use their output later with Ember controller actions.
Use Ember.Select http://emberjs.com/api/classes/Ember.Select.html
{{view 'select' value=someControllerProperty}}
It helps you keep logic inside the controller.
Now, in the controller you can react upon changes to the value selected with:
processValueChange: function() {
// do stuff
}.property('someControllerProperty')

in Ember how to pass in a parameter with link-to and use it in the rendered template?

I have to links that render the same template but they have different labels. Depending on which link the user clicks on, I want to show different text on my rendered template. Is there anyway to do this?
{{link-to "new_post"}}
and in my new_post.hbs I want to use this parameter. Assuming the parameter name is isValid
{{#if isValid}}
<h3> This is valid </h3>
{{else}}
<h3> This is not valid </h3>
{{/if}}
How can I do this?
Thanks!
Is this what you are looking for?
http://emberjs.com/guides/routing/query-params/#toc_link-to-helper
You can add query params to a link-to with this syntax:
{{#link-to 'posts' (query-params direction="asc")}}Sort{{/link-to}}

View-targeted action propagating to sibling views

I'm trying to implement a basic table, with two rows for each player object. One is the edit row, filled with text fields, the other is the view row.
In my main template I'm using a CollectionView to render out the set of rows (players is a collection)
<table>
{{view Ember.CollectionView contentBinding="players" itemViewClass="App.PlayerView"}}
</table>
I then defined a custom view to receive the click action:
App.PlayerView = Ember.View.extend({
templateName: 'rosters/player_view',
isShowVisible: true,
actions: {
toggleVisibility: function(){
this.toggleProperty('isShowVisible');
}
}
});
Finally, I created the template for the view:
{{#if view.isShowVisible}}
<tr>
<td>{{view.content.name}}</td>
<td><a {{action "toggleVisibility" target="view"}}>Edit</a></td>
</tr>
{{else}}
<tr>
<td>{{input type="text" value=view.content.name}}</td>
<td><a {{action "toggleVisibility" target="view"}}>Done</a></td>
{{/if}}
What I'd like to happen is that when I press the "Edit" link, it hides the text row, and shows the input row. What's happening is that it works fine if I press the first link, but, say I press the 10th link down, it will hide the show rows of 1-10, and then only show the edit of 10. It's almost like the event is propagating to the sibling views from the collection, or their attributes are somehow linked?
I tried setting "bubble=false" on the action, but that didn't solve anything, neither did returning false from my action, or preventing propagation inside there. An alert statement inside the action indicates that it's only being called once (so, not once for each sibling view). I'm new to Ember, so I'm open to any suggestions over what I'm doing wrong!
It's actually because of missing closing tr tag in the else statement. Although this is ultimately the issue, I think when metamorph rips out and adds the table rows the browser has issues, but that can easily be remedied by pulling the tr tags out of the if statement.
http://emberjs.jsbin.com/EXEnUZE/1/edit
<script type="text/x-handlebars" data-template-name="rosters/player_view">
<tr>
{{#if view.isShowVisible}}
<td>{{view.content.color}}</td>
<td><a {{action "toggleVisibility" target="view"}}>Edit</a></td>
{{else}}
<td>{{input type="text" value=view.content.color}}</td>
<td><a {{action "toggleVisibility" target="view"}}>Done</a></td>
{{/if}}
</tr>
</script>

Ember.js: yield specific object in layouts

I would like to create a layout in which I iterate over a collection with #each and then pass that object to yield. Is that possible?
What I would like achieve is:
<!-- timeline_layout.hbs -->
<div id="timeline-container">
{{#each entry in controller}}
<div class='timeline-entry'>
{{yield entry}}
</div>
{{/each}}
</div>
<!-- timeline_instance.hbs (timeline with posts) -->
{{#view App.Timeline}} <!-- has layout set to timeline_layout -->
{{render 'post' entry}}
{{/view}}
If guess that is not possible, right? Since render 'post' can't know about the entry. So what is the ember way to encapsulate the general html structure of the timeline?
"A template used as a layout must contain a single use of the Handlebars {{yield}} helper. " ember.js views. Your approach essentially breaks this rule, as you're trying to create a new yield for each entry in your controller- you should look at refactoring your each into the template.

Ember.js and handlebars each helper, with subviews

I'm triyng to use the view helper inside my {{#each}} template blocks without using global paths (my controllers create and destroy their own views).
Examples. Given a view with a myList array property, and an itemButton child view:
This will work
<script type="text/x-handlebars" name="my-list-view">
{{#each myList}} <!-- App.myListView.myList -->
{{view App.myListView.itemButton}} {{title}}
{{/each}}
</script>
This will not:
<script type="text/x-handlebars" name="my-list-view">
{{itemButton}} <!-- works fine outside the each -->
{{#each myList}}
{{view itemButton}} {{title}} <!-- itemButton view not found -->
{{/each}}
</script>
I do not appear to be able to access the parent view from the each view helper (or in fact access anything other than the properties of the objects being iterated).
The hacky workarounds I've come up with are:
Add the view I want to use to the items I'm iterating over.
or
Creating a collectionView in App.myListView
Create an itemViewClass view in that collection view class
Move the itemButton view inside the itemViewClass
Replace {{#each}} with {{#collection}}
or
Create a custom handlebars helper for iteration.
Both of these options seem horrible.
Surely there's a better alternative than creating 2 new classes (and nesting 4 views deep) just to iterate over a list, though. Is there a replacement handlebars helper I can use instead?
Workaround implementations
Option #1 : Modifing the content array
http://jsfiddle.net/FQEZq/3/
Disadvantages: Having to add the view to each model instance just for iteration.
Option #2 : Custom collection view
http://jsfiddle.net/ST24Y/1/
Disadvantages: Now you have two additional views that you do not need / want, and less control of markup. References from the child view to the parent instance now requires parentView.parentView.parentView.
#each is too limited for your requirements. You can make it work if you're willing to use a global path to the view you want to nest within the #each. Otherwise, your collection view approach is best. Adding the view to the model instance is likely to muddy your app design something fierce, so I would avoid that.
One idea to keep your templates clean is to take advantage of Ember.View properties like:
collectionView - Return the nearest ancestor that is an Ember.CollectionView
itemView - Return the nearest ancestor that is a direct child of an Ember.CollectionView
contentView - Return the nearest ancestor that has the property content.
The big thing here - options.
Hooks for how you wish to use a template are available. These are:
<-- render templates/name.js -->
{{partial 'name'}}
<-- render views/name.js -->
{{view 'name'}}
<-- render views/name1.js with controllers/name2.js -->
{{render 'name1' 'name2'}}
<!-- see also: -->
{{output}}
{{output 'named'}}
{{yield}}
An example variant of your initial template showing 4 different options:
<script type='text/x-handlebars' data-template-name='my-list-view'>
<h2>Option 1</h2>
{{#each myList}}
{{! the 2nd parameter will look for itemButtonController }}
{{render 'itembutton' itemButton}}
{{/each}}
<h2>Option 2</h2>
{{#each myList}}
{{! using an Ember Component }}
{{#item-button }}
some static text OR {{dynamic}}
{{/item-button}}
<!-- in component/item-button.hbs add {{yield}} for where you want the static content to output -->
{{/each}}
<h2>Option 3</h2>
{{#each myList}}
{{! if the button is to be a link }}
{{#link-to 'route' parameter tagName='button' classNames='btn'}}
{{title}}
{{/link-to}}
{{/each}}
<h2>Option 4</h2>
<p>Ludicrous example showing almost every reference option!</p>
{{! focus the context on subview data }}
{{#with someArrayOrCollectionOfView}}
{{! prepend type to add context - here returning back up to this view's properties }}
{{#each view.myList}}
{{! this is equivalent to someArrayOrCollectionOfView[x].name }}
{{name}}
{{! a button that hooks in route, model, and 2 controllers, and applies a target for the output when clicked }}
{{#link-to 'page' controllers.page.nextPage target='outlet' tagName='button' disabledWhen=controller.disableNext }}
{{model.buttonName}}
{{/link-to}}
{{/each}}
{{/with}}
{{! generic default target (automatic) }}
{{outlet}}
{{! example of a named target }}
{{outlet 'footerlinks'}}
</script>
Mmmm... reference for further reading:
Ember.Handlebars.helpers