The documentation has an example of using an ArrayController with this template:
{{#each MyApp.listController}}
{{firstName}} {{lastName}}
{{/each}}
This is how the ArrayController is used:
MyApp.listController = Ember.ArrayController.create();
$.get('people.json', function(data) {
MyApp.listController.set('content', data);
});
How would this work differently than using a plain array like this instead?
MyApp.listController = [];
$.get('people.json', function(data) {
MyApp.set('listController', data);
});
If you don't need the behavior of a controller, you can use a plain array.
An ArrayController wraps an array, with some other properties added, such as the sortable mixin.
You can see it here:
https://github.com/emberjs/ember.js/blob/master/packages/ember-runtime/lib/controllers/array_controller.js
in the ember.js documentation says:
(http://docs.emberjs.com/symbols/Ember.ArrayController.html)
The advantage of using an ArrayController is that you only have to set
up your view bindings once; to change what's displayed, simply swap
out the content property on the controller.
it uses an Array in background, only helps with methods to work with the array:
Although you are binding to the controller, the behavior of this
controller is to pass through any methods or properties to the
underlying array
Related
I have a simple array of ints that I'm displaying on a page.
This is my model:
var Favorite = Ember.Object.extend({
stuff: Ember.A([1,2,3,4])
});
This is my template:
{{#each model.stuff as |num|}}
<li>{{num}}</li>
{{/each}}
In my controller, modifications to this array generally display on the page (such as pushObject()), but modifying elements directly does not cause the page to update. I have a button on my page linked to this controller action:
actions: {
arrayAdd() {
this.get('model').stuff[0] = 100;
}
}
Clicking the button modifies the underlying array, but doesn't update the page. Is there a way to have ember automatically pick up on that change?
I'm doing this in Ember 1.13
Actually the equivalent of arr[idx] = foo for an ember array is arr.replace(idx, 1, [foo]).
The other thing you could do is to call this.get('model').notifyPropertyChange('stuff') after you manually edited the array.
In Ember, you need to use KVO(key value observer) compliant methods so that it will trigger computed property recalculation and observer and update the template. Always we need to use get for getting the properties and set for setting the values. if you didn't follow ember will throw assertion error sometime.
For array there are KVO methods which is equivalent to standard method.
Standard Method -> Observable Equivalent
pop -> popObject
push -> pushObject
reverse -> reverseObjects
shift -> shiftObject
unshift -> unshiftObject
In your case, you need to update it like the below, reference twiddle
arrayAdd() {
this.get('model.stuff').unshiftObject(100);
}
Note: You can declare array stuff: [1,2,3,4] it's good to initialize it in init method.
I still feel the array indexer should properly update the value,
though
Interestingly in glimmer component, you don't need to use getters/setters.
I'm having issues accessing input values within my component. I'm trying to dynamically create value bindings in my templates and accessing in the conponent.js file using this.controller.get("pst"+id) however the result is underfined. Using Ember 2.2
{{#each post in |pst idx|}}
{{input value=(concat 'pst' idx)}}
{{/each}}
Well, it works as expected, but why would you want to do this?
Please explain what you want to archive and then we can help better.
And to be clear, a value generated with the get helper is immutable.
Why not do something like {{input value=pst}}?
If this is not an option probably you should build your array in JS and use that then in handlebars!
Define a computed property that wraps your 'post' variable in your component.js file. Iterate over that wrapper. I think this is a powerful way of generating dynamic values.
Your template:
{{#each postWrappers as postWrapper}}
{{input value=postWrapper.value}}
{{/each}}
Your component.js:
postWrappers : Ember.computed('post', function() {
//your concat code
});
Does kendo ui support nested Datasources?
I have a table within which I need one of the columns to have a nested table. I am not using json to populate either.
In whatever little documentation I've been able to find it says that nested datasources arnt supported but those use json.
If someone could provide an example of how to implement this, it would be very helpful.
short answer: yes, the HierarchicalDataSource is just am immplementation of the normal datasource that nests. in other words each "node" is a instance of a datasource.
Kendo API Doc
there isn't a ton of documentation of how the HierarchicalDataSource works; I personally had to mess around a lot in the source code to get a handle on it. Kendo only uses it for the treeview and it seems to be built specifically for it. However, You can more or less get it behave how you want by altering the Node model passed into it.
You cannot just use this dataSource with any widget, the widget needs to support it internally. I personally had to create my own listview implemenation to work with it because i wanted nested CRUD .
This is a simple listview implementation that covers a nested template. While is not perfect it seems to be the simplest way to manage this challenge. I would also suggest that the question lacks clarity. I am reaching to answer what I believe to be the obstacle.
// Parent ListView
<div id="parent-listview"></div>
// Parent template
<script id="parent-template" type="text/x-kendo-template">
<a>#=ParentDescription#</a>
// Child ListView
<div id="child-listview-#=Id#"></div>
</script>
// Child template
<script id="child-template" type="text/x-kendo-template">
<a>#=ChildDescription#</a>
</script>
// Bind Parent
$("#parent-listview").kendoListView(
{
template: $("#parent-template").html(),
data : parentData
dataBound: function(e) {
// Bind children
$.each(this.dataItems(), function(idx, item) {
bindChildListView(item);
})
}
});
// Bind each child item
function bindChildListView(data) {
$("#child-listview-" + Id).kendoListView({
template: $("#child-template").html(),
dataSource: data.ChildItems
})
}
NOTE I have a simple int property called Id on my data objects but you can use the uid of the row if you need to or something else.
I have a Model called Course that has an array variable called users. Is there a way to just limit the results of, let say, IDs from users rather than the {{#each}} rendering every single id?
Such that
<script type="text/x-handlebars" data-template-name="course">
{{#each user in users 5}}
{{user.name}}
{{/each}}
</script>
Will show the first 5 IDs rather than every single id stored in users?
Here is the Ember-data model that I am using
App.Course = DS.Model.extend({
//Attributes
name: DS.attr('string'),
description: DS.attr('string'),
//Relations
users: DS.hasMany('App.User'),
});
I tried multiple times at creating a registerHelper, but where it always seems to go wrong is when an 'a in b' is present.
Any help or ideas would be appreciated. Thank you very much!
Rather than modifying the #each helper you could take a different approach to show only a limited amount of items when looping over the array with the #each helper.
See this for a possible implementation:
App.IndexRoute = Ember.Route.extend({
model: function() {
return [
Ember.Object.create({id:1, name:'Red'}),
Ember.Object.create({id:2, name:'Green'}),
Ember.Object.create({id:3, name:'Blue'})
];
}
});
App.IndexController = Ember.ArrayController.extend({
limitedContent: function() {
return this.get('content').splice(0, 2);
}.property('content')
});
The .property('content') defines a binding to the controller's content and takes care that the #each helper rerenders when the content changes.
And then in your template you loop over the limitedContent rather then the content:
<script type="text/x-handlebars" data-template-name="course">
{{#each color in limitedContent}}
{{color.name}}
{{/each}}
</script>
And here a working jsbin that show the concept mentioned.
Hope it helps
I was using the method in the accepted method, but ran into an issue with it.
The problem lay in that using splice in ember modifies the underlying data:
filtered: function() {
return this.get('content').splice(0,2);
}.property('content'),
splice removes the elements from the underlying content.
A better method is to use Ember's built-in slice function, changing the above code into
filtered: function() {
return this.get('content').slice(0,2);
}.property('content'),
And that's it, now it doesn't modify the underlying array, because slice returns a new array and leaves the underlying data untouched.
JSBin showing that splice modifies underlying data:
http://emberjs.jsbin.com/ridixawimugo/1/
JSBin with the fixed solution:
http://emberjs.jsbin.com/voceye/1/
Using http://www.lukemelia.com/blog/archives/2012/03/10/using-ember-js-with-jquery-ui/ I'm trying to implement a sortable list in a template loaded by an Ember.ArrayController which has an array of Phonenumbers as content :
{{#collection App.SortableListView contentBinding="phonenumbers" itemViewClass="App.SortableItem"}}
<b>{{phonenumber.cost}}</b>
{{/collection}}
I'm trying to update the 'order' property of each phonenumber after a sort but I can't figure out how to do that :
App.SortableListView = JQ.SortableListView.extend({
items: 'article',
//update is a jquery ui method called when the sort ends and dom has been updated
update: function(event, ui) {
// I would like to update and persist each phonenumbers model here
}
});
I have tried various things : bindAttr on order, data attributes through jquery, using the contentIndex property of each childView (but it's not updated when sorting)... Everything failed, or was too much complexity for such a simple thing.
I guess I'm missing something obvious, thx for your help.
There is sortProperty method on array controller that do what you want