Iterating over DS.hasMany in Ember data - ember.js

I have a real struggle with Ember.
In my model I have an attribute:
options: DS.hasMany('UserOptions', {async: false})
In a view linked to this model I can easily access this property by e.g.:
{{#each options AS |option|}}
something....
{{/each}}
and that works like a charm.
However when I try to access this model value in controller with:
this.get('model.options')
instead of getting a lovely array of payment options, I get an ember model array of objects, and there's no way I can access the actual data.
Do you guys have any idea how do I access this data in controller and process it?
Thanks!

this.get('model.options') will give you RSVP.Promise, so you need to work with asynchronous code. Use:
this.get('model.options').then(options => {
options.forEach(option => {
// do what you need with option
})
});

Below code solved my case:
#get('model.options').toArray().forEach((item) ->
console.log(item.get('parameter_name')]
)
That's true that console.log(#get('model')) was throwing something strange in console, however when I asked for a specific parameter, it was there!
My problem was that I was trying to print out an entire object instead of a specific value. The values were there, it just didn't print the entire object for a reason.

Related

EmberJS Filter Returned Data from Store

I'm new to Ember and trying to figure out the best way to filter data with Ember. I thought it would be by creating either a helper or a component but my attempts at implementing these solutions have failed miserably.
Having read a lot about this today and tried several options my brain hurts and I am no closer to a result.
I'm building a schedule for an upcoming sports season. The template currently renders all games. The idea is when you click on a team name, you will see only games for that team. The data displayed is being stored in Firebase (so EmberFire).
The ability to also filter by date would also be nice but I figure that's a problem for future Red.
Sorry for the vagueness of my question, I know what it is I want to do I just no idea how to get there.
Thank you!
Red
So it sounds like you want to use a query parameter to specify the team to filter by. In your Controller, specify the queryParams property and then create a computed property that returns the filtered list from the model:
queryParams: ['selectedTeam'],
selectedTeam: null,
filteredGames: Ember.computed('selectedTeam', 'model', function() {
let selectedTeam= this.get('selectedTeam');
let model= this.get('model');
if (selectedTeam) {
return model.filterBy('team', selectedTeam)
}
else {
return model;
}
Then, in your template, instead of using model, use filteredGames:
{{#each filteredGames as |game|}}
... render the {{game}} ...
{{/each}}
Hope that helps.

How to Live Update Ember Model with Search Results from API

Quick backgorund: I am creating a recipe app with Ember frontend and a Rails API backend. I am implementing a search feature to find recipes based on ingredients. I have already configured my Rails API endpoint which sends back the correct records. My problem now is that I am having a very difficult time live updating my results, ie. the model data is not updating the template. This seems like a trivial problem, but for whatever reason I haven't been able to figure it out.
Here is what my project looks like:
model(params) {
this.store.query('recipe', {query: params}).then( response => {
console.log("RESPONSE", response);
})
}
recipes index.hbs (this does not currently update):
{{recipe-card-container recipes=model}}
How can I solve this?
Well, I feel stupid. Forgot a return before this.store.query -__-
You not only forgot the return, but you also are failing to set the model correctly due to your debugging statement. Should be:
model(params) {
var result = this.store.query('recipe', {query: params});
result.then(response => console.log("RESPONSE", response));
return result;
}
With your code, even after adding a return, the return value from model will be a promise which resolves to the value of the function printing out the response, which is undefined.

Ember distinguish record which is requested from server with params and without params

I'm trying to get two records from the server without knowing the ID's. The first record is requested without params and the second record with params.
It looks something like this:
model: function(){
return Ember.RSVP.hash({
cars: this.store.find('cars').then(function(car){
return car.get('firstObject');
}),
carsWithRange: this.store.find('cars', {date_from: momentLast30Days}).then(function(car){
return car.get('firstObject');
})
});
}
At the moment 'cars' and 'carsWithRange' sometimes returns the same record. I think this is happening because I use car.get('firstObject') from the cars models. Somehow I need to know that 'carsWithRange' is requested with the param 'date_from'.
Does anyone know how to fix this?
FYI I use Ember 1.12.1 with Ember Data 1.0.0-beta.15
We finally solved it in the frontend by using this.store.findQuery (with a query which doesn't make a lot of sense) instead of this.store.find. This returns the exact record which is given by the server. But yeah it feels a bit hacky.

Dynamically add js object to model array in 1.13

I have the following code:
var msg = this.store.createRecord({text:'first title', createdAt: "2015-06-22T20:06:06+03:00" })
this.get('model.content').pushObject(msg);
msg.save();
We create new record. Then push in it to the model to display. It worked perfectly in 1.9 version but after upgrading it to the newest 1.13 it breaks and shows this error:
TypeError: internalModel.getRecord is not a function
after some researches I came out to this solution
this.get('messages.content').unshiftObject(message.internalModel);
and it partially help. Now I have two problems:
I'm not confident if using private ember data api is a good idea
I have an annoying delay between adding record to the model and
rendering it on the screen. More than that if I don't call
msg.save(); the record isn't rendered. So as far as I understood it
waits until we have response from server and only then renders it.
But I need opposite behaviour - I need to show the record first and
then save it(showing the saving state for the user), this way user
thinks that everything goes extrimely fast.
One possible solution without resorting to private API is to use toArray() (github issue):
var array = this.get('messages').toArray()
array.addObjects(this.get('messages'))
array.addObject(msg)
this.set('messages', array)
Before 1.13:
this.get('content').pushObjects(messages);
After 1.13:
messages.forEach(functio(message) {
this.get('model.content').pushObject(message._internalModel);
});
I would make all return models to array then, add array to this array
setPeople:function(){
this.set('people',this.get('content').toArray())
}.observes('content')
then, find more person models, to array
getMoreUsers(){
var self = this;
this.set('offset', this.get('offset')+1);
self.store.findAll('person').then(function(people){
self.get('people').pushObjects(people.toArray());
});

In ember data, calling destroyRecord in a forEach loop is corrupting the loop?

I'm working on a simple Tag model for one of my projects. I've implemented something similar in Angular, but I wanted to give it a try in Ember. The model code is below
Tag = DS.Model.extend {
name:DS.attr('string')
user:DS.belongsTo('user')
appliedTags:DS.hasMany('AppliedTag')
obliterate:()->
#destory the associated applied tags
this.get('appliedTags').forEach( (appliedTag)->
console.log(Ember.inspect(appliedTag))
appliedTag.destoryRecord()
)
#destory the record
this.destroyRecord()
}
fixtures = [
id:1
name:'Category 1'
user:1
appliedTags:[1,5]
]
Tag.reopenClass
FIXTURES: fixtures
Everything is fine if I comment out appliedTag.destoryRecord(). However with it in, on the second time through the forEach loop, appliedTag is undefined.
Modifying the contents of a collection while iterating will cause major issues. That's the issue that you're seeing here, you're destroying records, which modifies the collection that's being iterated. Ember's hasMany collection will remove records when they are removed from the store/destroyed. The easiest solution is to copy the contents to a different array that won't get modified when you perform those kinds of operations.
this.get('appliedTags').toArray().forEach( (appliedTag)->
console.log(Ember.inspect(appliedTag))
appliedTag.destoryRecord()
)