Ember JS - Updating / Refreshing Model data From Route Action - javascript

This seems to be very simple problem but I can't find any solution for this. I want to refresh the data for unprocessedDailyDataFile from action. I can get the model by modelFor() method. But when I try to use get() and set() method with the model they fails as undefined.
Code for Route
App.AdminRoute = Ember.Route.extend({
model: function(){
return {
companies: this.store.find('company'),
unprocessedDailyDataFiles: this.store.find('unprocessedDailyDataFile')
};
},
actions: {
reloadUnprocessedDailyDataFile: function(){
var model = this.modelFor('admin');
// both properties from the model is accessible here
// model.get() fails
// model.set() fails
}
}
});

For the model to reload, you can use
actions: {
reloadUnprocessedDailyDataFile: function(){
let model = this.get('controller.model'); // for Get and Set
model.get('name');
model.set({ name: 'john'});
}
}

Related

Ember: Even after refresh some attributes in the model are not changed

I am new to EmberJS, and facing problem with model data updation
Controller :
export default Ember.Controller.extend({
queryParams: ['jobid'],
jobid: null,
currentCount: null,
actions: {
onOffToggle(e) {
var isChanged = this.get('model.b.isChanged');
this.set('model.b.enable', e.target.checked);
this.set('model.b.isChanged', !isChanged);
console.log(this.get('model.b.isChanged'))
},
iterationCountChange() {
var currentCount = this.get('currentCount');
var isCountChanged =
(currentCount != this.get('model.b.count')) ? true : false;
this.set('model.b.isCountChanged', isCountChanged);
}
}});
Route:
export default Ember.Route.extend({
ajax: Ember.inject.service(),
beforeModel: function (transition) {
this.jobid = transition.queryParams.jobid;
},
model(){
return Ember.RSVP.hash({
a: this.store.queryRecord('a', {jobid: this.get("jobid")}),
b: this.store.queryRecord('b', {id: this.get("jobid")})
});
},
setupController: function(controller, model) {
this._super(controller, model)
controller.set('currentCount', model.b.get('iterationCount'))
},
actions: {
paramChange(a, b)
Ember.$.ajax({
url: "/rest/test",
type: 'POST',
contentType: 'application/json',
data: JSON.stringify({
b: b,
a: a
})
}).then(response => {
this.refresh();
})
},
error(error, transition) {
if (error.errors[0].status == 404) {
return this.transitionTo('not-found', { queryParams: {'previous': window.location.href}});
}
}
}
});
Here in controller I am keeping track if some value have changed, and if they have changed then update the flag related to their change, these flags like isChanged and isCountChanged are the part of the model's data, after user cliks submit button , paramChange
action is called and then a post call is made to update the db for respective property changes, and then this.refresh() is called to render the latest model data.
But the problem is, once isChanged and/or isCountChanged are changed from their default value, then they don't reset to the new value present in the model data, e.g. after refresh the value to both these flags should be reset to false but it comes always true, I checked the value in the setUpController hook for the values of these flags and it confirms to true.
According to me it has something to with the controller, since any value which is used in controller once is not resetting to new value coming after refresh.
Kindly help I am spent a lot of time in this and got nothing till now, do inform if any extra information is required.
Ember version: 2.6
From docs,
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.
So, if your model data doesn't change, setupController() is not called. My approach is to have a custom method to update controller with model data. Then, I call this method from model() hook (for this.refresh()) and from setupController().
model() {
return this.store.query(....).then(data => this.updateControllerData(data));
}
setupController(controller, model) {
this._super(...arguments);
this.updateControllerData(data);
}
updateControllerData(data = {}) {
if (!this.controller) {
return;
}
this.controller.setProperties(data);
}
Note that if setupController() is not fired, the controller data is always updated.

Emberjs: Handling form submission, params, access to model

(Warning: newbie) Going around the block on this one, as each example I see does it differently (and none work for me)
var InitiativesNewRoute = Ember.Route.extend({
model: function(params) {
return this.store.createRecord('initiative', params);
},
actions: {
submit: function() {
var initiative = this.get('model');
initiative.save().then(function(model) {
this.transitionTo('initiatives.show', initiative);
});
}
}
});
Saving barfs as initiative is undefined, but I see a record created in the ember chrome plugin. So it looks like creating the record in model works, but fetching it in the action doesn't.
Also tried this example:
submit: function(initiative) {
initiative.save().then(function(model) {
this.transitionTo('initiatives.show', initiative);
});
}
Without passing passing params to createRecord above, and I get the same error. How do I do this?
Using ember-cli 0.0.39 and easy-form, with the fixture adapter.
Got some help on #emberjs and managed to get it working like this:
var InitiativesNewRoute = Ember.Route.extend({
model: function(params) {
return this.store.createRecord('initiative', params);
},
actions: {
submit: function() {
var _this = this;
var initiative = this.get('controller.model');
initiative.save().then(function(model) {
_this.transitionTo('initiatives.show', model.get('id'));
});
}
}
});

EmberJS: initialize nested model with parent model loaded by ajax

I got the following simple ember.js-setup, which works all great
App.Router.map(function() {
this.resource('tourdates', function() {
this.resource('tourdate', { path: ':tourdate_id' });
});
});
App.TourdatesRoute = Ember.Route.extend({
model: function() {
return $.getJSON('http://someapi.com/?jsoncallback=?').then(function(data) {
return data;
});
}
});
App.TourdateRoute = Ember.Route.extend({
model: function(params) {
return tourdates.findBy('id', params.tourdate_id);
}
});
so, pretty simple, whenever i call index.html#/tourdates, i get the data via api. and when I click on a link in this view and call f.e. index.html#/tourdates/1 it just displays the view for its nested child.
This all breaks, when I directly call index.html#/tourdates/1 with the message
DEPRECATION: Action handlers contained in an `events` object are deprecated in favor of putting them in an `actions` object (error on <Ember.Route:ember174>)
Error while loading route: ReferenceError {}
Uncaught ReferenceError: tourdates is not defined
Although he makes the ajax-call to the api and gets the data, he is not able to initialize the nested model
When your App.TourdatesRoute is loaded, all data from the json, will be rendered. And when you click to edit one of these loaded objects, using a link-to for example, ember is smart enough to get the already referenced object, instead of send a new request. So your url will change to: yourhost.com/tourdate/id.
When you direct call this url, it will call the App.TourdateRoute model method. Because doesn't have any pre loaded data. But in your case you have a:
tourdates.findBy('id', params.tourdate_id);
And I can't see in any place the declaration of tourdates.
I recommed you to change your TourdateRoute to TourdateIndexRoute so when transitioning to tourdates the ajax call is performed once:
App.TourdatesIndexRoute = Ember.Route.extend({
model: function() {
return $.getJSON('http://someapi.com/?jsoncallback=?').then(function(data) {
return data;
});
}
});
The TourdatesRoute is called both for TourdateRoute and TourdatesIndexRoute, because it's the parent route of both. So fetching all data in the TourdatesIndexRoute will ensure this is just called when transitioning to tourdates.
In your TourdateRoute you will load just the record needed. Something like this:
App.TourdateRoute = Ember.Route.extend({
model: function(params) {
// retrieve just one data by id, from your endpoint
return $.getJSON('http://someapi.com/' + params.tourdate_id + '?jsoncallback=?').then(function(data) {
return data;
});
}
});
So a direct call to yourhost.com/tourdate/id will just loaded one record.
About your warning message, it happens because in some route you have:
App.MyRoute = Ember.Route.extend({
events: {
eventA: function() { ...},
eventB: function() { ...},
}
});
The events is deprecated and you need to use actions:
App.MyRoute = Ember.Route.extend({
actions: {
eventA: function() { ...},
eventB: function() { ...},
}
});
I hope it helps

Ember Data - TypeError: Object has no method 'eachRelationship'

So, I'm trying to build routes in my Ember application dynamically with data from an API endpoint, /categories, with Ember Data. In order to do this, I'm adding a didLoad method to my model, which is called by the controller and set to a property of that controller. I map the route to my router, and all that works fine. The real trouble starts when I try to set up a controller with a content property set by data from the server retrieved by findQuery.
This is the error:
TypeError {} "Object /categories/548/feeds has no method 'eachRelationship'"
This is the code:
window.categoryRoutes = [];
App.Categories = DS.Model.extend({
CATEGORYAFFINITY: DS.attr('boolean'),
CATEGORYID: DS.attr('number'),
CATEGORYNAME: DS.attr('string'),
CATEGORYLINK: function () {
var safeUrl = urlsafe(this.get('CATEGORYNAME'));
categoryRoutes.push(safeUrl);
return safeUrl;
}.property('CATEGORYNAME'),
didLoad: function () {
var categoryLink = this.get('CATEGORYLINK');
var categoryId = this.get('CATEGORYID');
App.Router.map(function () {
this.resource(categoryLink, function () {
// some routes
});
});
App[Ember.String.classify(categoryLink) + 'Route'] = Ember.Route.extend({
setupController: function(controller, model) {
// source of error
this.controllerFor(categoryLink).set(
'content',
this.store.findQuery('/categories/' + categoryId + '/feeds', {
appid: 'abc123def456',
lat: 39.75,
long: -105
})
);
}
});
}
});
Any 'halp' is appreciated!
Also, if I'm doing this completely wrong, and there's a more Ember-like way to do this, I'd like to know.
I figured this out. I got this error because I was passing in a string instead of a real 'type' from the App.Helpers object to an extract method in some custom RESTAdapter code I had overridden.
The solution is to pass in the corresponding model helper in App.Helpers using my custom type name.
Something like this in the overridden RESTAdapter.serializer.extractMany method:
var reference = this.extractRecordRepresentation(loader, App.Helpers[root], objects[i]);

Ember.js - Asyncronous call in model find() method

I have implemented find() and findAll() methods on my Property model. Both methods make asynchronous calls to an API. findAll() is called while connecting the outlets for my home route, and works fine. find() is called by Ember.js while connecting the outlets for my property route. Note that find() is not called when navigating to a property route through actions, but is called when you go directly to the route through the URL.
Here is my router:
App.Router = Ember.Router.extend({
root: Ember.Route.extend({
showProperty: Ember.Route.transitionTo('property'),
home: Ember.Route.extend({
route: '/',
connectOutlets: function(router) {
router.get('applicationController').connectOutlet('home', App.Property.findAll());
}
}),
property: Ember.Route.extend({
route: '/property/:property_id',
connectOutlets: function(router, property) {
router.get('applicationController').connectOutlet('property', property);
}
}),
})
});
And here are my findAll() and find() methods:
App.Property.reopenClass({
find: function(id) {
var property = {};
$.getJSON('/api/v1/property/' + id, function(data) {
property = App.Property.create(data.property);
});
return property;
},
findAll: function() {
var properties = [];
$.getJSON('/api/v1/properties', function(data) {
data.properties.forEach(function(item) {
properties.pushObject(App.Property.create(item));
});
});
return properties;
}
});
When I go to a route other than index, for example http://app.tld/#/property/1, the route gets rewritten to http://app.tld/#/property/undefined. Nothing is being passed to the content property of the Property controller. How can I make asynchronous calls in the find() method? Unless I am mistaken, asynchronous calls work fine in the findAll() method, which is the source of my confusion.
This question is similar to Deserialize with an async callback, but I'm using the find() method instead of overriding the deserialize() method.
Thanks in advance.
I found that setting the id property explicitly solves this problem. In your case this would look like this.
find: function(id) {
var user = App.User.create();
$.getJSON('/api/v1/property/' + id, function(data) {
user.setProperties(data.user)
});
user.set("id",id); // <-- THIS
return user;
}
Once your user gets its properties set the view updates as normal. Ember just need the id part before in order to update the URL.
Hope this helps :-)
Here's what you want to be doing. I changed the model to User to make things a little clearer.
In the case of find(), you return a blank model instance that gets it's properties filled in when the AJAX request comes back. The nice thing about Ember's data-binding is that you can display this model in a view immediately and the view will update when the AJAX request returns and updates the model instance.
In the case of findAll(), you return a blank array that gets filled in when the AJAX request comes back. In the same way as find(), you can display this list of models (which at first will be blank) in a view and when the AJAX request returns and fills in the array, the view will update.
App.User.reopenClass({
find: function(id) {
var user = App.User.create();
$.getJSON('/api/v1/property/' + id, function(data) {
user.setProperties(data.user)
});
return user;
},
findAll: function() {
var userList = [];
$.getJSON('/api/v1/properties', function(data) {
var users = data.users.map(function(userData) {
return App.User.create(userData);
});
userList.pushObjects(users);
});
return userList;
}
});

Categories