EmberJS calling controller function within #each - ember.js

I'm trying to call a controller function inside a #each template to check if the model is selected. This needs to receive the model for each loop iteration.
jsbin is here http://emberjs.jsbin.com/bemos/4/edit
I've tried using the following template, but adding a parameter to {{controller.selected}} results in ember throwing an exception, or not doing anything (the result seems to be different in jsbin).
{{#each model}}
<li><a hres="#" {{action "clickItem" this}}>{{label}} -- selected is {{controller.selected name}} </a></li>
{{/each}}
My function in the controller looks as follows
selected: function(id) {
var list = this.get("selectedList");
console.log("Checking sel for", id);
if(list.contains(id))
return true;
return false;
}.property("selectedList")
In the jsbin, I expect to be able to click on the "Hello 1"/"Hello 2" elements, and this should change the part of the text that says "selected is false" to true. It should also update the number of items selected in the bottom. Currently, this shows 1 item is selected (since the default is selectedList:["2"]) however "Hello 2" says "selected is false" - this should say "true".
(I should add I'm pretty new to EmberJS as have been working with ExtJS for a few years!).
Thanks

Do you really have a problem in code ? I guess no, since your bin is working fine and even clickItem is working as well. In your local environment where you are facing this issue, I think you are not using same version of handlebars and ember. Please check if you are using below,
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="http://builds.handlebarsjs.com.s3.amazonaws.com/handlebars-v1.3.0.js"></script>
<script src="http://builds.emberjs.com/tags/v1.6.1/ember.js"></script>
Update 1 -
Here is the bin I tried to update - http://emberjs.jsbin.com/veqoqocu/1/edit
Its not fully functioning but fixes some issue.
There are multiple problems,
You should use ArrayController for lists, redesign your example otherwise selected property will never work the way you want. Here is a good example - http://emberjs.com/guides/controllers/representing-multiple-models-with-arraycontroller/
push & pop needs to be pushObject and popObject
computer property on array works like - }.property('selectedList.[]')

Related

How do you use Ember.js addons?

I'm evaluating Ember.js for possible use in an upcoming project. I want to see now it fares with a long list of items, so I tried to installed the ember-list-view.
I ran the command:
ember install:addon ember-list-view
The syntax seems to have changed, so I ran
ember install ember-list-view
That activates npm, which downloaded the package successfully. I can see it in node_modules. Then per the documentation I created the following:
templates/test.hbs:
{{#view 'list-view' items=model height=500 rowHeight=50 width=500}}
{{name}}
{{/view}}
routes/test.js
import Ember from 'ember';
// define index route and return some data from model
export default Ember.Route.extend({
model: function() {
var items = [];
for (var i = 0; i < 10000; i++) {
items.push({name: "Item " + i});
}
return items;
}
});
I added the route in router.js. When I go to the page, nothing shows up. According to Ember Inspector, the right template was being used and the data was there. A check on Ember.ListView in the console yield undefined.
Is there something more that needs to be done to bring in the code? Searches in the Ember and Ember-CLI documentation yielded no answer.
It looks like a problem with the list-view documentation.
There are two issues here:
The {{view}} helper is not a block helper (as far as I know. FYI a block helper is a helper that begins with {{#some-key-word}} and ends with {{/some-key-word}}) - You can't wrap content in it and have that content displayed in the view.
The list-view expects the property content not items
When you change the code to the following:
{{view 'list-view' content=model height=500 rowHeight=50 width=500}}
It works a little bit better (e.g. you can inspect the page and see item views being created) - but still not what you're expecting.
When you change the view keyword to the ember-list keyword (which ember-list-view registers as a helper) - everything works.
{{#ember-list items=model height=500 rowHeight=50 width=500}}
{{name}}
{{/ember-list}}

display last object from dynamically updating array + emberjs + handlebars

I am using rails 4 with emberjs. I have an array of users that I get from the server. I need to display the last object on the UI. Also, the user can add new users to the array but only the last/latest-added user should be visible.
My ember version details are as
Ember : 1.7.0-beta.1
Ember Data : 1.0.0-beta.8.2a68c63a
Handlebars : 1.3.0
jQuery : 1.11.1
My current handlebars code is as. After adding the new user to users array, the new user details is displayed.
{{each users}}
//display all the users here.
{{/each}}
What i want is something like this
{{#each users}}
{{#if #last}}
//display user details
{{/if}}
{{/each}}
I tried adding a property in the associated controller and removed the 'each' loop. I displayed the lastUser details which works. But if I add a new user, the UI still displays
the previous user details.
lastUser: (->
return #model.users.get('lastObject')
).property('#model.users')
How can this be acheived? Thanks.
You can simply use the following:
{{users.lastObject.firstName}}
{{users.lastObject.lastName}}
or more cleanly:
{{#with users.lastObject}}
{{firstName}}
{{lastName}}
{{/with}}
With just redefines this within the block to the object provided--in this case the users.lastObject object. Your lastUser computed property is unnecessary because Ember enumerables already provide this for free!
To watch additions to the users array, you need to watch the 'users.#each'
See the following documentation http://emberjs.com/guides/object-model/computed-properties-and-aggregate-data/

Combining view class with layout and {{#each}} multiple times gives incorrect behavior

I'm seeing some very strange behavior in this jsfiddle.
I am building an accordion control (hopefully eventually a good contribution to ember-bootstrap), and so I built a view class that uses layout to wrap the contents of the view:
Bootstrap.Accordion = Ember.View.extend({
tagName: 'div',
classNames: 'accordion',
layout: Ember.Handlebars.compile('{{yield}}')
});
Then I use it like so, with the {{#view}} helper, and include an {{#each}} block which will eventually include other views to set up the inside of the accordion control. And in one case so far, I do this twice in the same template, to display different information in two different accordion controls, sort of like this:
{{#view Bootstrap.Accordion}}
{{#each content}}
<div><strong>Field 1:</strong> {{field1}}</div>
{{/each}}
{{/view}}
{{#view Bootstrap.Accordion}}
{{#each content}}
<div><strong>Field 2:</strong> {{field2}}</div>
{{/each}}
{{/view}}
But, as you can see in the fiddle, this produces a very unexpected result. Basically, the second instance of the view is an exact copy of the first. Even the static content inside the {{#each}} block is not right:
Field 1: Instance 1 Field 1
Field 1: Instance 2 Field 1
Field 1: Instance 1 Field 1
Field 1: Instance 2 Field 1
However, if I put something between the {{#view...}} and {{#each}} helpers, it behaves as expected:
{{#view Bootstrap.Accordion}}
Fourth try...
{{#each content}}
<div><strong>Field 4:</strong> {{field4}}</div>
{{/each}}
{{/view}}
So, it looks like something about the similarity of the content directly within the {{#view}} helper causes the result to be cached by Handlebars...or something. That's just a wild hypothesis. Can anyone see what's going wrong here?
(Note that the Bootstrap library is not included in the fiddle, so it can't be that Bootstrap is goofing something up.)
This looks like a bug.
This github issue was created today, only with the {{#linkTo}} helper.
Looks like this is occurring with all block helpers.

View click action not returning correct object

I'm having trouble with a click handler in a view. It's not returning the expected member of the collection, but the collection as a whole.
I've created a jsfiddle to demonstrate the issue. I have an ArrayController, whose content I pre-populate. The view for this controller then uses the #each helper for the controller with another view:
{{#each controller}}
{{view App.ActivityListItemView}}
{{/each}}
This works, in that I see the name of the item on the page, and can click it.
The problem is in the click handler - if I #get('content'), the content for the parent controller is returned. How do I get the item that was clicked on? If you have a look at the console output in the jsfiddle you'll see the issue. I assume this is a context issue?
I've tried adding contentBinding="this" to the view:
{{#each controller}}
{{view App.ActivityListItemView contentBinding="this"}}
{{/each}}
but that makes no difference.
thanks,
Martin
How do I get the item that was clicked on? If you have a look at the console output in the jsfiddle you'll see the issue. I assume this is a context issue?
Exactly. You want the view's context instead of it's controller's content. So:
click: (data)->
console.log 'clicked on an activity'
selected = #get('context')
#get('controller').set('selectedActivity', selected)
console.log(#get('controller').get('selectedActivity.name'))
Why?
By default the {{#each}} helper does not create a new controller instance for items in the array. So when you#get('controller')` from the view helper it searches up the view heirarchy until a controller is found - in this case that is the array controller.
If you want to have a separate controller for each item you could provide an itemController attribute to the each helper - see http://emberjs.com/api/classes/Ember.Handlebars.helpers.html#method_each
Right, I've got this working, I think the issue sprang for a lack of understanding of the contentBinding argument. Basically I've changed to using a specific name of 'activityBinding' within the #each block, and then referring explicitly to the activity in the click handler. See jsfiddle for a working demo.
{{#each controller}}
{{view App.ActivityListItemView activityBinding="this"}}
{{/each}}
and
click: ->
console.log 'clicked on an activity'
console.log #get('activity.name')
content = #get('activity')
#get('controller').set('selectedActivity', content)

Morph fails to remove in IE 8/9

I'm working on an Ember app (using RC1) and am having a problem with IE (surprise). We have a series of nested views that can show either a trip's summary, details, or edit. The trip view looks (roughly) like this:
{{#if tripController.showSummary}}
{{template "view/TripSummaryView"}}
{{/if}}
{{#if tripController.showDetails}}
{{template "view/TripDetailView"}}
{{/if}}
{{#if tripController.showEdit}}
{{template "view/TripEditView"}}
{{/if}}
On the div surrounding the trip summary view, I have an action:
<div {{bindAttr id="tripController.tripId"}}
class="card single-line"
{{action "toggleDetails" tripController on="click"}}
style="cursor:pointer">
And the controller handles the action:
toggleDetails: function(tripController) {
if (this.get('showDetails')) {
this.set('showDetails', false);
this.set('showSummary', true);
} else {
this.set('showDetails', true);
this.set('showSummary', false);
}
},
All pretty vanilla, and it works perfectly in Chrome, FF, and Safari. But when I run it in IE, it bombs in the metamorph's realNode() function (line 17264 in ember.js):
var realNode = function(start) {
while (start.parentNode.tagName === "") {
start = start.parentNode;
}
return start;
};
with this error:
SCRIPT5007: Unable to get value of the property 'parentNode': object is null or undefined
When I put a breakpoint in the code, it appears that Ember is trying to remove 2 metamorphs, but that the second is inside the first and so start is null the second time around. I put a breakpoint in that function in Chrome, but it doesn't ever appear to get called.
I've tried reducing this down to a JSFiddle, but I can't seem to get it to break - so there must be something in the way we've got our views set up that's causing a problem. Any suggestions on how to go about debugging this would be most appreciated!
Thanks,
Scott
You can achieve the same using ContainerView but I am also facing similar problem where childviews are not receiving model/controller. Here is a [similar post] (An example of ContainerView required where childViews are binded with their respective controllers "containerview's childviews controller binding")