I have a filter and I can't get it to resolve the promise. It is using a model called 'patient' that hasMany 'addresses' and I want to filter out the address that has an addressType of 'Primary'. The filter seems to be working but only will return a promise. Thank you in advance for the help.
Patient controller
App.PatientController = Ember.ObjectController.extend
primaryAddress: Em.computed 'model.#each.addresses', ->
#get('model.addresses').then (addresses)->
addresses.filterBy 'addressType', 'Primary'
Solution (Thanks to #GJK)
primaryAddress: Em.computed 'model.addresses.#each', ->
#get('model.addresses').filterBy('addressType', 'Primary').get('firstObject')
The most obvious issue that I can see is that you're not watching the #each property of the addresses. Your property depends on model.#each.addresses, which means that your model is an array, and you're observing the addresses property on each item in that array. But you're not observing the content of the addresses array, just the array itself.
It seems to me that you should use model.addresses.#each as your dependent property. This will observe all addresses on a single model, including observing the contents of the addresses array (which updates when the promise resolves).
EDIT: Also, I didn't quite read far enough apparently. You shouldn't be calling then on the promise. Treat it as if it's already resolved, and it'll be updated when it does resolve. So use this instead:
App.PatientController = Ember.ObjectController.extend
primaryAddress: Em.computed 'model.addresses.#each', ->
#get('model.addresses').filterBy 'addressType', 'Primary'
The first time this property comptues, the promise will be unresolved so the filter won't return anything. But when the promise resolves, the property will update and the filter will work like you expect it to.
Related
Let's say I have a list of records that are supposed to have state selected in some current context. I can see two approaches here:
Create an array of objects: records.map(record => { record: record, selected: false }), get and set like `recordObj.set('selected', true). Render this array.
Set property explicitly on record objects: record.set('selected', true). Render RecordArray.
The second one looks much easier than the first as you don't have to manage additional array and objects (this becomes a real hassle).
The problem is that if you set anything on a record object, even a field that is not present in the model, it will still persist through the application (I guess until the model is reloaded and new record object is created?).
How to prevent that and ensure that temporary properties will be clean on every route change? Or how to improve the first approach? Is there anything I'm missing?
In route file
actions: {
willTransition() {
let records = this.get('controller.records');
records.setEach('selected', false);
}
}
This will make sure every time you leave route you are safe.
this.store.findAll('game').then(function(results){
// RUN SOME OPERATION ON THEM
})
I would like to know how I can play with the results variable. I understand I can do
results.get('firstObject') // returns the first object.
I'd like to know everything else I can do with it. Is there any api documentation for the results collection?
Thanks!
From ember guides,
The below methods, will return the Promise, it will be resolved to Record or RecordArray.
store.findAll() returns a DS.PromiseArray that fulfills to a DS.RecordArray.
store.findRecord returns a promise that will be resolved with the record.
store.query() returns a DS.PromiseArray in the same way as findAll.
The below two are synchronus method, it will retrieve what is available in the store and returns record itself. it will not request the server to fetch data.
store.peekAll directly returns a DS.RecordArray.
store.peekRecord direclty returns record
It's important to note that DS.RecordArray is not a JavaScript
array, it's an object that implements Ember.Enumerable. This is
important because, for example, if you want to retrieve records by
index, the [] notation will not work--you'll have to use
objectAt(index) instead.
From Ember.Enumerable, most of the time I happened to use the following,
forEach to iterate
map to transform to new Array
filterBy findBy for filtering based on single property check
toArray converting to normal native array
findAll will return a Promise which will resolve to a RecordArray.
The RecordArray is an ArrayProxy.
http://emberjs.com/api/classes/Ember.ArrayProxy.html
This is everything you need.
If you google "ember findall" you will find docs for "Ember.js - Models: Finding Records - Guides" as well.
https://guides.emberjs.com/v2.5.0/models/finding-records/
I am trying to retrieve records which have already been loaded into the store by using this line in a controller:
var allProducts = this.store.all('product');
However, this is returning a strange object (see screenshot). When I call length on it, the result is "undefined." I have used the Chrome Ember inspector to confirm that records have indeed been loaded into Product before the above line of code is run. I thought since store.all returns a recordarray I could iterate over it immediately unlike a promise. Where am I going wrong please?
The strange object that is returned is a record array. This is important so that Ember can set up observers for arrays that are loaded. I believe this is what is causing your confusion. See more specifics in the docs:
It's important to note that DS.RecordArray is not a JavaScript array.
It is an object that implements Ember.Enumerable. This is important
because, for example, if you want to retrieve records by index, the []
notation will not work--you'll have to use objectAt(index) instead.
You will have to look at the documention for DS.RecordArray but you should be able to iterate over it using the forEach method. See the ember array documentation for more details.
The issue was that I was trying to iterate over the recordarray using a traditional for loop. Seems that a) recordarray cannot return length and 2) one must use a forEach loop to iterate over it, which is what I had initially did but dropped because forEach does not support break or continue.
Ahh promises! :)
You should be able to do this:
var allProducts = this.store.all('product').then(function(products) {
return products;
});
is there a way to know why a record is in a dirty state in ember data, I mean what are the attributes and relations that has changed.
I'm having isDirty = true after calling a findAll and I want to debug why this happens.
Thanks a lot
As of Ember-Data beta 6 or earlier, there is a changedAttributes() function that returns a hash of the attributes that are changed, and their initial/current values. See http://emberjs.com/guides/models/working-with-records/
For example:
person.changedAttributes(); //=> { isAdmin: [false, true] }
Note that changedAttributes() is not a property that you can observe; however, if you needed to do so, you could observe all the properties that might change on the model, and then check changedAttributes() inside your computed property/observes function.
For (contrived) example:
checkAttributes: (->
changed = #get('model').changedAttributes()
if changed['name'] && Object.keys(changed).length == 1
# Do something if name is the only changed attribute
).property('name', 'alias', 'description')
Depending on which version of ember-data you're using (and, now, what you're using as an adapter) this could be different. The behavior changed in version 9. Before then, you could say record.isDirtyBecause('belongsTo') and if the record had been marked dirty because the belongsTo relationship had changed, it would return true. Now, due to some shifts in the responsibilities between Stores and Adapters, it's up to the Adapter to handle this.
If you still need this information in your adapter, it will be your responsibility to do any bookkeeping in the dirtyRecordsForAttributeChange hook described above.
I'm new to ember and am still getting my sealegs under me with the framework. So far I think its great, except there is one thing that I can't seem to figure out: how to bind a property of an array item to a property of an adjacent array item.
Details:
My model is like so:
App.SRDate = Ember.Object.extend({
timeValue: null,
reductionAmount: null,
id: null,
index: null,
date: Ember.computed(function(){return formatted date as a string}).property('timeValue') ,
previousDate: ???
});
And I have a simple arraycontroller that just holds a list of the above objects. What I am trying to do is be able to call App.dates.objectAt(1).get('previousDate') and have it return App.dates.objectAt(0).get('date'). I got it to kind of work initially by using a computed property for the previousDate, but it would only update when I changed an item in bound object (i.e. if I changed the date for object 0 it wouldn't update in previousDate for object 1 until I changed the date in object 1, which caused ember to re-evaluate the computed property). If there is a way to define what objects a computed properties are associated with, then that would probably do the trick, however I don't think that is what computed properties are really supposed to be used for...
I also tried a binding like:
previousDateBinding: 'App.dates.getObject('+this.get('index')-1+').date'
but that didn't work either.
Thanks in advance for any help with this.
Just had a similar problem, here's how I solved it: http://jsfiddle.net/aMQU6/1/
In my ArrayController, I have a function that observes changes to my content. Then once it is added, I set a property in the new object to be the previous object, then bind the previous object's date to the previousDate property in the added object.
Hope this helped! Let me know if you have any questions.