I updated to RC6 two weeks ago, and I'm noticing an error in one of the screens in the project I'm working on. I have an ember model, which has a hasMany relation, that model as a computed property based on a property on its hasMany relationship, something like this:
notReadyToSend: function() {
return this.get('tweets').filter(function(tweet){
return !tweet.get('readyToSend');
})
}.property('tweets.#each.readyToSend')
this belongs to the tweet model:
readyToSend: function() {
//if all properties are true, then this property returns true
}.property('title', 'body', 'alreadySent', and many other properties)
and, at the time in which the data is being loaded, all the tweets are not 'ready' because you know, data is being loaded, but when the whole data is loaded, some tweets remain not 'ready' in the 'notReady' property, but they are actually 'ready' in their object, I mean, the Tweet ember model hast its 'ready' property, which also has some logic, and that property is true, but the 'notReady' property is not fired, and this happens for the last(depends how many we have, sometimes only one, sometimes two, etc) tweets.
Is anyone experiencing this issue ?
I've updated the code, but as a note, those are not the real models, but that's basically what I'm doing. the readyToSend property, gets set to true for all records, but the notReadyToSend property in the parent model, doesn't get updated, but again, this does not happen with all the records, just a few ones(and only the last in in the relationship) do not fire the parent property.
One more update, I have another property in the parent model, which also checks one property of the tweets relationship, it looks like this:
hasAtLeastOneTweetALreadySent: function() {
return this.get('tweets').findProperty('alreadySent');
}.property('tweets.#each.alreadySent')
and the 'alreadySent' property is also being observed in the 'readyToSend' property of the tweet model. And for some reason, if I just comment out that(hasAtLeastOneTweetALreadySent) property, everything works fine, do you know why this is happening ? this is weird.
Related
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.
I'm creating a component for rendering tables. The component is actually a set of nested components and receives a route model and config object, at the top level, then is processed within the component and passed on / iterated over in the next etc.
The final child component receives a model (representing just one row in the table) along with field name that defines which filed to display from the model.
All of this works perfectly and UI updates are bound to the model. The problem that I have is that model updates are not being pushed to the UI. Within my child component I bind to the UI element using the following:
tdVal : function(){
return this.get('data').get(this.get('details').get('field'));
}.property()
tdValUpdated : function(){
this.get('data').set(this.get('details').get('field'),this.get('val'));
}.property('tdVal'),
As you can see there is no computed property literal set for tdVal, which is why model updates are not being pushed to the UI. If I were to give this a literal value such as 'data.status' then status updates to the model are pushed to the UI.
What literal value can I use to compute on any attribute change in the model?
I've tried 'data.isUpdated', 'data.isSaving' etc. I can't use 'data.[]' as the single model, not an array of model.
OK, after much trial and error I think I've found a workaround for this. It's messy and I'm not very happy with it:
//as previous I render the the appropriate value from the model as defined
//by the passed in config object
tdVal : function(){
return this.get('data').get(this.get('details').get('field'));
}.property(),
//then detect UI changes and push to model if required
tdValUpdated : function(){
this.get('data').set(this.get('details').get('field'),this.get('val'));
}.property('tdVal'),
//Then I observe any changes to model isSaving and directly set tdVal with
//the value of the field for the current td
generalUpdateCatch: function() {
this.set('tdVal',this.get('data').get(this.get('details').get('field')));
}.observes('data.isSaving'),
I did try the following instead:
tdVal : function(){
return this.get('data').get(this.get('details').get('field'));
}.observes('data.isSaving'),
But get the error: 'Uncaught TypeError: unsupported content', no idea why? If anybody has a better solution then please post as I very much dislike these workarounds.
Going throught the getting started tutorial for ember js and I am somewhat confused by what the differences are in doing
function(){}.property('model.isCompleted')
and
function(){}.property('isCompleted')
Specifically, what is the model for?
The model is just another property, but instead of being a primitive such as a string or a number its an object.
For:
model = {
prop1: 'fi',
prop2: 'fai',
prop3: 'fo',
prop4: 'fu'
}
If you do this: function(){}.property('model.prop3') your computed property will be updated only when prop3 changes.
If you do this: function(){}.property('model') your computed property will be updated when model changes.
And model is a property in your controller set by the route you are in.
Is there a nice way to force Ember Data to load the resource from server eaven if it has it already in store ?
I have a simple show user action that do store.find('users',id) the model is loaded only once at first attempt to display a page the second time i go my model is loaded from the store which is normal ember data behaviour i know. However i need to load it each time.
edit:
the only way i found is to do this :
#store.find('user',{id: params.user_id}).then (users)->
users.get('firstObject')
however it forces me to implement a "fake" show action on my index action ...
I think this... http://emberjs.com/api/data/classes/DS.Model.html#method_reload
model.reload()
Good luck
Additionally you can call getById which will return any instance of that record that exists, or null, then call unloadRecord to remove it from the cache. I like Edu's response as well though, then I wouldn't have to worry about the record existing somewhere else. Maybe I'd use getById then reload that way any references that had a reference to the user got updated. (pardon my errant coffeescript, if it's wrong).
user = #store.find('user', params.user_id)
if (user)
#store.unloadRecord(user)
Hot off the presses, thanks to machty:
There's a new method getting added as part of the query params feature going into beta this weekend called Route.refresh()...
/**
Refresh the model on this route and any child routes, firing the
`beforeModel`, `model`, and `afterModel` hooks in a similar fashion
to how routes are entered when transitioning in from other route.
The current route params (e.g. `article_id`) will be passed in
to the respective model hooks, and if a different model is returned,
`setupController` and associated route hooks will re-fire as well.
An example usage of this method is re-querying the server for the
latest information using the same parameters as when the route
was first entered.
Note that this will cause `model` hooks to fire even on routes
that were provided a model object when the route was initially
entered.
#method refresh
#return {Transition} the transition object associated with this
attempted transition
#since 1.4.0
*/
You can do this in the setupController hook, using a promise, and the reload method mentioned by Edu.
setupController: ->
#store.find('myModel', 1).then (myModel) ->
myModel.reload()
If you are sure that records to display will change after a certain action then you can call this.refresh() method in your Route. For example:
ProductsRoute = Ember.Route.extend
model: ->
#store.find 'product',
activated: true
actions:
accept: (product) ->
if not product.get('activated')
product.set 'activated', true
product.save()
.catch (err) ->
console.log err
product.rollback()
.then =>
#refresh()
ignore: (product) ->
if not product.get('ignored')
product.set 'ignored', true
product.save()
.catch (err) ->
console.log err
product.rollback()
.then =>
#refresh()
If actions are called from child route - e.g. products/proposed - models will be reloaded for parent route and also child routes.
I think that what you are looking for is DS.Store#fetchById
It seams simple, but I'm stuck on this one. I have a single controller, and single view dedicated to order model, which has nested client. I create empty records on setupController:
route:
ShowroomApp.OrdersRoute = Ember.Route.extend
model: ->
ShowroomApp.Order.createRecord()
setupController: (controller,model) ->
model.set("client", ShowroomApp.Client.createRecord() )
controller.set("content", model )
controller:
save: ->
#content.store.commit()
On OrdersController i have save action to commit changes made in the form. It results in two separate POST requests each one for each model, but the association doesn't build itself. Orders model saves first, and client_id is obviously null because client doesn't exists yet. Later goes Client post and saves the client, but Order model doesn't know about it and stays without client.
Is there any solution to that?
Thanks,
J
This is due to an outstanding ember-data issue - RESTAdapter: Allow new parent, child to be saved at once
Check out Tom Dale's Comment for a possible workaround. It involves manually adding support for saving both records at once.
As an alternative, you might consider adding a onCreate callback to the parent record, then creating the child in the callback. If you are ok with having a second commit() this will get the job done.