This is a follow up to: accessing another models data in ember.js
I have a situation where I would like to filter a list with a chosen multi-select box. When sending the data, this.store.find('tag') always returns a DS.PromiseArray. The Ember.Select seems to handle this fine, but the chosen multi select doesn't seem to like it. I have seen something like this:
this.store.find('tag').then(function(items) {
return items.map(function(item){
return [item.get('id'), item.get('name')]
})
})
but I always seem to get a typeerror{} on the map function...
Here is a jsfiddle that outlines the problem:
http://jsfiddle.net/viciousfish/TEZjW/
Bonus Points! demo shows the chosen select as a single select (for clarity). I would like to use this as a multi select, which can be set by setting multiple: true in App.MultipleSelect
Update here is another jsfiddle with what I think should work, but doesn't seem to! http://jsfiddle.net/viciousfish/FZ6yw/1/
And even further, this fiddle shows that the .then should work to deconstruct the promiseArray http://jsfiddle.net/marciojunior/DGT5L/
Here is a functional jsfiddle http://jsfiddle.net/FZ6yw/2/
I moved the promise code to the afterModel hook of the route, as is promise friendly https://gist.github.com/machty/5723945
I also changed the map function, you were returning arrays and in my code it returns objects
App.AssetsRoute = Ember.Route.extend({
model: function () {
return this.store.find('asset');
},
afterModel: function () {
var self = this;
return this.store.find('tag').then(function(items) {
var allTags = items.map(function(item){
return {id:item.get('id'), name:item.get('name')};
});
self.controllerFor('tags').set('content', allTags);
})
},
});
Related
I'm trying to change the query of a filtering select's data store, such that the dropdown only displays the values that were queried with a query such as this (note that I can't even get it to work with a non-regex query):
var query = {
id: new RegExp("^(1|12)$")
};
See this JSFiddle.
Note that I do not want to fetch the result set using
dropdown.store.fetch({query: query, onComplete: function(results) {} });
I want the results to filter in the dropdown.
Despite viewing this and several other related questions, I haven't been able to get a solution that works for a FilteringSelect as I intend. Any help is appreciated.
To do what I was trying to do, you have to query the FilteringSelect, not the store.
dropdown.query.id = /^(1|12)$/;
But even better, this works for all queries, not just regex, since the function can be anything:
dropdown.query.id = {
test: function (id) {
return [1, 12].indexOf(id) > -1;
}
};
Note: This query property is inherited from dijit/form/_SearchMixin. See the properties of FilteringSelect.
I am creating a generic table view that can be used with different collections. Here is an example of what I'm trying to do:
...
getModelIdAttribute: function () {
return this.collection.__proto__.model.prototype.idAttribute;
},
getModelFromRow: function (HTMLrow) {
return this.collection.get(this.dataTable.row(HTMLrow).data()[this.getModelIdAttribute()]);
},
...
The data() function returns an object with the attributes that were used to create the model, but I want to account for different idAttributes.
Currently, my way works - but __proto__ is deprecated and it seems like there should be an easier way that I am missing?
Thanks
I have a simple action that can be attached to list items in an {{#each}} loop, and when that action is triggered, it will link to that instance of the model.
This is what it looks like now
VpcYeoman.SuperTableController = Ember.ArrayController.extend({
actions: {
goTo: function(input) {
this.transitionToRoute('someModel', input);
}
}
});
The action is called on an HTML element like this
{{action 'goTo' this bubbles=false}}
You can see the problem with this in that 'goTo' cannot be reused on other models because it is specifically looking at the 'someModel' model.
Please help me make this action work for whatever the current model is
I tried replacing 'someModel' with a generic 'model' & even 'this.model' but they didn't work.
Do not reply with 'use {{#link-to}}' please. I am aware that this exists and
Before you read this, you should know that I do recommend you use the link-to helper. I normally pass a computed property to the helper when I need it to change based on the model...
I am not sure where you have that action in your code, but you could just compute that path as needed. For example, take this item controller:
App.ItemController = Ember.ObjectController.extend({
getTransitionPath: function () {
return this.get('foo') + '_bar';
},
transitionPath: function () {
return this.get('foo') + '_bar';
}.property('foo'),
actions: {
goTo: function(input) {
//this.transitionToRoute(this.getTransitionPath(), input); // Regular method
this.transitionToRoute(this.get('transitionPath'), input); // Computed property
}
}
});
I also don't know what kind of logic you are looking for inside of those methods, but this pattern should work on a per model basis.
Good luck!
I have a route that creates a new record like so:
App.ServicesNewRoute = Ember.Route.extend({
model : function() {
return this.store.createRecord('service');
},
setupController: function(controller, model) {
controller.set('model', model);
},
});
Then I bind that model's properties to the route's template using {{input type="text" value=model.serviceId ... }} which works great, the model gets populated as I fill up the form.
Then I save record:
App.ServicesNewController = Ember.ObjectController.extend({
actions : {
saveService : function() {
this.get('model').save(); // => POST to '/services'
}
}
});
Which works too.
Then I click the save button again, now the save method does a PUT as expected since the model has an id set (id: 102):
But then when I look at the PUT request in Dev Tools, I see that the id attribute was not serialized:
As a result, a new instance is created in the backend instead of updating the existing one.
Please ignore the serviceId property, it is just a regular string property unrelated to the record id which should be named just id.
I don't know why the id is not being serialized... I cannot define an id property on the model of course since Ember Data will not allow it, it is implicit. So I don't know what I am missing...
Any help is greatly appreciated!
The base JSONSerializer in Ember-Data only includes id in the payload when creating records. See DS.JSONAdapter.serialize docs.
The URL the RestAdapter generates for PUTting the update includes the ID in the path. In your case I believe it would be: PUT '/services/102'.
You can either extract it from the path in your backend service. Or you should be able to override the behavior of your serializer to add the id like this:
App.ServiceSerializer = DS.JSONSerializer.extend({
serialize: function(record, options) {
var json = this._super.apply(this, arguments); // Get default serialization
json.id = record.id; // tack on the id
return json;
}
});
There's plenty of additional info on serialization customization in the docs.
Hope that helps!
Initially I used ronco's answer and it worked well.
But when I looked at ember data's source code I noticed that this option is supported natively. You just need to pass the includeId option to the serializer.
Example code:
App.ApplicationSerializer = DS.RESTSerializer.extend({
serialize: function(record, options) {
options = options ? options : {}; // handle the case where options is undefined
options.includeId = true;
return this._super.apply(this, [record, options]); // Call the parent serializer
}
});
This will also handle custom primary key definitions nicely.
Well, as far as I know it's a sync issue. After first request you do the post request and then, it has been saved in the server, when you click next time the store haven't got enough time to refresh itself. I've got similar issue when I've created something and immediately after that (without any transition or actions) I've tried to delete it - the error appears, in your case there's a little bit another story but with the same source. I think the solution is to refresh state after promise resolving.
We were using a model with a hasMany with embedded children. This was fine so that whenever I called model.get('children') everything just worked.
We've now changed that children property to async:true, and I can't seem to find proper documentation on how you should handle this.
Let me give you an example. I'll use simplified json to represent my Ember setup, just for the sake of simplicity.
Say I have a Model like this:
model:{
hasMany: {children: {async: true} },
isActive: boolean
}
Say I have a Template like this:
{{#if lastChildIsActive}}
<p>I'm the last one!</p>
{{/if}}
And I have a Controller:
controller:{
lastChildIsActive: function(){
return this.get('model').get('children').get('lastObject').get('isActive')
}
}
Ok, so with this setup when async: false was being used, everything just worked.
But now, with async true, that call in the controller for .get('children') SOMETIMES just doesn't return anything, because it's async I guess.
Now I could use promises, and refactor my controller to this:
controller:{
lastChildIsActive: function(){
this.get('model').get('children').then(function(children){
return children.get('lastObject').get('isActive');
});
}
}
The problem with the second refactor is, I'm not longer returning the isActive value, I'm now returning the promise object.
But the template doesn't want a promise, it needs the returning value.
SO, how can I make sure the async has loaded, while being able to return the actual result of the call instead of the promise?
By using a view and didInsertElement, you can get the children of the parent and then update the attribute on the controller, which will appear in your template.
App.IndexView = Ember.View.extend({
didInsertElement: function() {
controller = this.get('controller');
controller.get('model').get('children').then(function(children){
active = children.get('lastObject').get('active');
controller.set('lastChildIsActive', active);
});
}
});
See this fiddle: http://jsfiddle.net/f9DAc/2/
You have to use observer to listen for the changes in children. Refer the change I have made in lastChildIsActive method below. As children is an array type, I am listening for "children.#each". Whenever, there is a change in "childern", lastChildIsActive will be updated automatically.
controller:{
lastChildIsActive: function(){
return this.get('model').get('children').get('lastObject').get('isActive')
}.property('children.#each')
}