Sorting Ember ArrayController when iterating the model - ember.js

I have an ArrayController (documents) which displays a list of ObjectsControllers (document) for its content.
My ArrayController template (Documents):
{{#each document in model}}
{{render "document" document}}
{{/each}}
The issue I am facing is that the "sortProperties" and "sortAscending" properties on the ArrayController are no longer having any effect. I assume this is because I am looping "model". If I loop "each document in controller", the document ObjectControllers dont seem to get the model assigned to them as a call to .model then throws an undefined error. Should I be looping "controller" or "model"? If the answer is model, how can I sort it and if the answer is controller, how can I get the model set on each controller?

Rather than modifying the base model, the sorted collection is exposed as arrangedContent.
To explain why it's arrangedContent rather than arrangedModel, in Ember's ControllerMixin content is defined as an alias for model, but it used to be the other way around.

You may have to set the itemController property on your ArrayController (Documents).
See here: http://emberjs.com/api/classes/Ember.ArrayController.html
Edit: Also, you had it right the first time with {{#each document in controller}}. Doing it straight from the model will ignore configuration in your controller, which includes sorting rules you may have.

Related

Emberjs - how do I set a property on an itemController from a route?

I have an ArrayController that uses associated itemControllers to track a checked property on the set of models (i.e. whether or not their checkbox is checked).
This part is currently working fine. When I come back to the route, I need to use some information off of the user model to "remember" which were checked.
How can I set the checked property on the specific itemController's? I can get references to the individual models that need "checking", but model.set('checked', true) doesn't seem to get picked up by the itemController in that scenario.
Any help would be appreciated!
From your array controller, iterate this and that will give you each individual itemController. Here's the basic concept
App.FooController = Em.ArrayController.extend({
someFunc: function(){
this.forEach(function(item){
item.set('checked', item.get('model.wasChecked'))
});
}
});

Ember.js: {{render}} does set 'content', but does not set 'model'

From my main handlebars dashboard template I am rendering multiple templates in a loop, setting the model as following
{{#each forecastDispatch in forecastDispatches}}
{{render "balance.forecastDispatch" forecastDispatch}}
{{/each}}
The dashboard combines multiple models and renders them on the same page/route.
From logging to the console, I can see that the BalanceForecastDispatchController controller gets instantiated correctly for each render call and the forecastDispatch model of type DispatchType is set as content, but not as model, model is still undefined. As the model is not populated properly, passing data to lower level components does not work. I thought that the model is just an alias/proxy for content, hence I am quite surprised.
What am I missing here? Any help is really appreciated, I am trying to solve this for quite some time now, but cannot find the culprit.
The issue was caused by snippets in my Handlebars template which were not commented out properly. As a result, one extra instance of the BalanceForecastDispatchController was created by Ember. This controller had off course no model/content assigned to it. In the Chrome Ember-inspector the controller was shown without a model.

Difference Between controller and controller.content

I have an ArrayController and was using {{#each item in controller}} to iterate over the items in the controller. This was working fine while using the same controller however after switching to another route I ran into some weird behavior which stopped the items from being rerendered. Switching to {{#each item in controller.content}} solved this problem. However I am not sure how this even happened.
What's the difference between controller and controller.content in an each expression (or any where else).
What's the difference between controller and controller.content in an each expression (or any where else).
Basically there is no difference, for example when using an ArrayController which extends from ArrayProxy, then inside the controller this.pushObject(obj) will behave the same as doing this.get('content').pushObject(obj). See here for reference.
But IMO you are better of using model everywhere e.g. {{#each item in model}}.
Check also this answer which I guess will be useful: Ember iterations: when to use #each User, #each user in controller, #each user in model, etc
Hope it helps.

Ember Getting property from Controller in Model

I have a computed property on a model and in order to compute that I need a property from a controller (not the one that is controlling the model).
I know there is needs: but this is just on
a controller level.
How could I get a property in Ember from a controller other than the one that is managing the model?
I'm trying to do some formatting like the person that [asked this question][1] but I didn't succeed what has been suggested there.
So I try to do the formatting on the model with a computed property, but to calculate that property I need another property from a controller.
Any help is greatly appreciated! Thanks!
Note: I'm using EmberData to manage the model.
Edit:
In order to clarify what I'm trying to do I have set up an example that shows the problem
in a general way: The example application lets you input numbers, store them,
and show them in a list. You can also input a "conversion factor" which doesn't change the model data itself but the presentation on the template. Say, you input the number 2, 2 gets saved on the model but when it is shown in the list it gets "formatted" with the conversion factor you entered previously and the calculated value is shown in the template. The problem is that the value with which I want to format is stored on a different controller. Here's what I have tried so far:
#1 Approach:
Computed Property on the ArrayController - using needs: in the controller to traverse and get the value
-->jsfiddle
Problems I have encountered:
The ArrayController seems to break and the template renders as if there are no stored records at all (Note: the example uses local storage, so create some records and uncomment the computed property on the ArrayController and you'll see it works originally as expected and shows the records you entered).
#2 Approach:
Computed Property on model itself
-->jsfiddle
Problems I have encountered:
I have no idea how I can get a property from a controller while beeing inside the model
#3 Approach:
Handlebars Helper and needs: on the controller
1) Define a computed property on the controller (that handles the model) to get the value in question from the other controller
2) create a handlebars helper and pass in the value from the model and the value from the controller and return the calculated value
-->jsfiddle (You can find the link for the 3rd jsfiddle in the comments since I don't have enough reputation points yet).
Problems I have encountered:
Instead of displaying the formatted number I get "NaN" on every value in the rendered template.
If anyone has an idea how to solve this or can point me into the right direction would be great. Your help is really appreciated! Thanks for your time!
Accessing any controller from a model is really going against the grain of Ember's architecture. Most formatting problems are best solved with a Handlebars helper, but if you need to combine data from the controller and model in a really serious way, then you probably want a computed property on the controller.
Can you give a concrete example of what you're trying to do? That will make it a lot easier to suggest the right solution.
I got it working: I've used the #3 Approach (outlined in my question).
I'm using a computed property to proxy the value from the other controller to the controller that is bound to the template where I want to display the formatted value
I created a handlebars helper called converted that will do the formatting. The handlebars helper accepts two parameters: the value that I proxy from the controller (which in turn comes from a different controller) and the value from the model.
The thing that didn't work previously was that in the template when using the helper I would get "NaN" on all items instead of the formatted output.
What solved the problem was that instead of lopping through the model in the template with:
{{#each controller}}
<tr>
<td>{{converted amount conversionFactor}}</td>
</tr>
{{else}}
<tr>
<td>No amounts here yet</td>
</tr>
{{/each}}
I changed it to this:
{{#each item in controller}}
<tr>
<td>{{converted item.amount conversionFactor}}</td>
</tr>
{{else}}
<tr>
<td>No amounts here yet</td>
</tr>
{{/each}}
and it works perfectly!
Here's the working jsfiddle

Ember JS - Reference view inside linkTo

I have an Ember JS confusion. First of all I have to admit I'm a bit of an Ember newbie so apologies if this is obvious.
I have the following template:
<script type="text/x-handlebars" data-template-name="threadListItem">
{{#linkTo show thread.receiverLogin}}
<h4>{{thread.receiver.login}}</h4>
<span>{{view.prettyTime}}</span>
{{/linkTo}}
</script>
There's basically a linkTo helper with some elements inside of it.
The weird thing is the {{view.prettyTime}} doesn't display anything when it's inside the linkTo.
However, if I move the span outside the linkTo it finds the view variable ok and it works.
Is there anyway to get access to the view object inside the linkTo?
Christopher is correct that you can access the prettyTime property with:
{{view.parentView.prettyTime}}
Since you're new to ember, it's maybe worth mentioning that in most cases it is best to avoid accessing properties of the view. Instead, consider adding a prettyTime property to your controller. The controller will be the default context for sub-views like the one created by the linkTo helper, so you'll be able to access it with just
{{prettyTime}}
linkTo creates its own view, so the view you want to get access to is the parentView of view.
{{view.parentView.prettyTime}}