I try fill ember controller without setupController hook, like this:
Ember.$.getJSON('http://url.com').then(function (response) {
self.store.pushPayload('record', response);
self.get('controllers.consultation').set('model', self.store.push('consultation', response.consultation));
});
Model for controller consultation contain hasMany field records
export default DS.Model.extend({
records: DS.hasMany('record', { async: true }),
....
});
When I call controller.records in templates it's doesn't works (empty), but other fields works fine.
Question: why controller.records empty?
NOTE: When I create field in consultation controller which contain consultation object it's works.
self.get('controllers.consultation').set('controllerObj', self.get('controllers.consultation').set('model', self.store.push('consultation', response.consultation)));
I'd try to resolve model.records immediately after model.
var controller = this.get('controllers.consultation');
Ember.$.getJSON('http://url.com').then(function (response) {
// ... your magic with store
// var consultation = consultation instance extracted from response
controller.set('model', consultation);
return consultation.get('records'); // or your custom api request for model.records
}).then(function (records) {
controller.set('modelRecords', records) // or your custom request records extraction
});
Then in controller you could set computed records:
// controller
records: function() {
// your logic here
}.property('modelRecords.[]')
and {{records}} should work in template
//template
{{records.length}}
Related
So what I am doing is extremely basic: rendering model data to the template.
Upon setting the model hook, the {{model}} object doesn't show data in the corresponding template.
Here's my code:
contact (route):
user: Ember.inject.service('current-user'),
model: function()
{
// var that = this;
// console.log('whats being returned bitch: ', this.store.findRecord('contact', this.get('user').contactID));
//return this.store.findRecord('contact', this.get('user').contactID);
var records = this.store.findRecord('contact', this.get('user').contactID);
var promise = Ember.RSVP.defer();
// console.log('promise', promise.resolve());
// records.addObserver('isLoaded', function() {
// // console.log('records.getv', records);
promise.resolve(records);
//});
return promise;
},
setupController: function(controller)
{
// Get the parameters for the current route every time as they might change from one record to another
var params = this.paramsFor('dashboard.contact');
console.log('params', params);
// Set the data in the current instance of the object, this is required. Unless this is done the route will display the same data every time
this.module = Ember.String.capitalize(params.module);
this.id = params.id;
this.data = this.store.find(this.module,this.id);
// Set the data in the controller so that any data bound in the view can get re-rendered
controller.set('id',this.id);
controller.set('model',this.data);
controller.set('module',this.module);
}
});
First i was trying just this but it was not displaying data, then i tried deferring the promise and resolving it (like this) and finally i tried setting up the controller (setupController function) but that didn't work either since params is empty for some reason :/
contact(template):
<h1> Contact! </h1>
{{#each model as |contact|}}
<h3>{{contact.name}}</h3>
<h3>{{contact.password_c}}</h3>
{{/each}}
contact(model):
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string'),
password_c: DS.attr('string'),
birthdate: DS.attr('string'),
assistant: DS.attr('string'),
account_name: DS.attr('string'),
email1: DS.attr('string'),
facebook: DS.attr('string'),
phone_home:DS.attr('string')
// address: Ember.computed('primary_address_street', 'primary_address_state',
// 'primary_address_city', 'primary_address_country', function() {
// return '${this.get('primary_address_street')} ${this.get('primary_address_state')} ${this.get('primary_address_city')} ${this.get('primary_address_country')}';
// })
});
Please help!
Let's assume this is your router
// app/router.js
import Ember from 'ember';
var Router = Ember.Router.extend({
});
Router.map(function() {
this.route('contacts', {path: '/contacts/:contact_id'});
});
export default Router;
and your model
// app/models/contact.js
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string'),
password_c: DS.attr('string'),
});
then this is would be your contacts.js route it will have a very important role and We'll be using Ember Data's findRecord to retrieve an individual record from the data store.
// app/routes/contacts.js
import Ember from 'ember';
export default Ember.Route.extend({
model(param){
return this.store.findRecord('contact',param.contact_id);
}
});
note: this param is very important.The param is passed from the URL into the model. This posts model has an id that can be accessed via contact_id. It uses that id to look up the record so it can be returned. By default the template with the same name, contacts, will have access to this model.
Here we use Ember Data's findAll. This simply returns back all the records in the post data store.
// app/routes/application.js
import Ember from 'ember';
export default Ember.Route.extend({
model() {
return this.store.findAll('contact');
}
});
now
// app/templates/application.hbs
{{#each model as |contact|}}
<h3>{{contact.name}}</h3>
<h3>{{contact.password_c}}</h3>
{{/each}}
As I don't have access to see your service and all your code I tried to simplify the way you can return all contact and get that and also how you can pass Param easily.
for more information : https://guides.emberjs.com/v2.7.0/tutorial/ember-data/
You can follow this codes and customize as you would like, I hope it will resolve your problem.
UPDATE:
If you have already your user data and it's ok, then remove {{#each}}
and let's have {{contact.name}}, that should work, you just need #each
while you have all contact like this.store.findAll('contact'); or if
you are in you must have this {{model.name}}, then model would be
contact !
I am a bit conceptually confused about how this works.
The user enters data on the form, presses next. The controller 's nextStep action fires and I ask the model to get data from the server. When the data arrives, I transition to the results route. At that point, I have the route store the previous model on a variable on the controller. Then I want to iterate through the data on the template.
The problem is that nothing shows up.
This is what I have (in the appropriate files):
//Step 1 Controller (partial - nextStep action)
var businessmatch = this.store.find('businessmatch', {businessname: businessname, phonenumber: phonenumber, zipcode: zipcode})
.then(function (result) {
// The model has data at this point
controller.transitionToRoute('step2');
});
// step2 Router
import Ember from 'ember';
export default Ember.Route.extend({
setupController: function(controller, model) {
controller.set('businessmatches', this.store.find('businessmatch'));
}
});
// Step2 template (partial)
{{#each businessmatches}}
{{businessname}}
{{/each}}
// Model
import DS from 'ember-data';
var Businessmatch = DS.Model.extend({
businessname: DS.attr('string'),
phonenumber: DS.attr('string'),
address: DS.attr('string'),
pageurl: DS.attr('string'),
thubmurl: DS.attr('string')
});
export default Businessmatch;
// Sample response from server
{
"businessmatches":[
{
"businessname":"El Farolito",
"pageurl":"/biz/el-farolito-san-francisco-2",
"thumburl":"/bphoto/ohpxQWg-hB9Sb27HkVg-yQ/90s.jpg",
"address":"780 El Camino RealMillbrae, CA 94030",
"phonenumber":"(650) 583-0487",
"id":1
},
{
"businessname":"El Farolito",
"pageurl":"/biz/el-farolito-san-francisco-4",
"thumburl":"/photo/AW76YTovuu9YsO69_BcLKQ/30s.jpg",
"address":"2779 Mission StSan Francisco, CA 94110",
"phonenumber":"(415) 824-7877",
"id":2
},
{
"businessname":"El Farolito",
"pageurl":"/biz/el-farolito-san-francisco",
"thumburl":"/bphoto/LgTOTIicRY6XArigmPhBpw/90s.jpg",
"address":"2950 24th StSan Francisco, CA 94110",
"phonenumber":"(415) 641-0758",
"id":3
}
]
}
#tstirrat is correct, the store.all() method immediately returns an array of cached records, while the store.find() method returns a promise of fetched records.
Is there a specific reason you aren't using the model hooks in your route? They are promise aware, and will wait for your store.find() to resolve then pass the model on to your setupController. You can then reference the previous models with modelFor('step1') or just use store.all() again.
Found it, if I change
controller.set('businessmatches', this.store.find('businessmatch'));
to
controller.set('businessmatches', this.store.all('businessmatch'));
it works as expected.
Would be interested to know why though, if anyone can explain.
My template:
{{#each test11}}
{{businessname}}
{{/each}}
My controller that works:
// businessmatches is a model that is set as a controller property in the router
test11: function () {
var raw = this.get('businessmatches');
// I want to be able to get all the records, filter them etc etc and then
// make them available to the template
return [
Ember.Object.create(raw.content.get(0)._data)
];
}.property('businessmatches'),
raw.content.get(0)._data feels like a hack, so I must be missing the proper way of doing this. How can I work with businessmatches records properly and make the new set available on the template?
Edit
From the router:
setupController: function(controller, model) {
controller.set('businessmatches', this.store.all('businessmatch'));
}
The model:
import DS from 'ember-data';
var Businessmatch = DS.Model.extend({
businessname: DS.attr('string'),
type: DS.attr('string')
});
export default Businessmatch;
test11: function(){
// give me all the records that have the property foo that is 11
var bms = this.get('businessmatches').filterBy('foo', 11);
// give me all the records that have the property bar that is 12
bms = bms.filterBy('bar', 12);
// other filtering etc
return bms;
// watch foo/bar on each record, if they change, recompute this computed property
}.property('businessmatches.#each.{foo,bar,...}')
I have a simple Ember app with 2 models related to each other: parent and record:
// parent model
export default DS.Model.extend({
records: DS.hasMany('records', { async: true })
});
// record model
export default DS.Model.extend({
parent: DS.belongsTo('parent')
});
Record routes are nested under parent routes and parent template contains link-to records and an outlet to render the content in. Records template contains simple {{#each}} loop.
Here is the records index route that is responsible for setting model:
// records index route
export default Ember.Route.extend({
model: function() {
return this.modelFor('parent').get('records');
}
});
When I load parent/records route all records load/render fine. The problem starts when I try to create new record; which I do in records index controller:
// records index controller
export default Ember.ArrayController.extend({
needs: ['parent'],
actions: {
createRecord: function() {
var newRecord = this.store.createRecord('record', {
parent: this.get('controllers.parent.model')
});
newRecord.save();
}
}
});
After I create new record it doesn't appear inside my records index template. If I open Ember inspector I can see the record there, it even has the correct parent record assigned.
Here is the answer I am getting from the server after creating the record:
{ "record": { "id": 1, "parent_id": 1 }}
I think the problem occurs because of record index route or response from the server; if I change route like this, new records appear as intended after creation (although thats not what I want; I want just the records that belong to the parent record):
// records index route
export default Ember.Route.extend({
model: function() {
return this.store.find('record');
}
});
I am on Ember 1.6.1 and Ember Data beta 8. Any ideas what might be wrong?
You're correct, your index route grabs an Array of models — it doesn't know that they have been updated or removed.
There are two ways to solve this: use a filter array or update the array manually.
Here is a link to question on the same subject:
Ember template not updating from arraycontroller
I'm using ember 1.0 and ember-data 1.0.0 beta 1. I have the following routes and controller to create and save simple notes ('AuthenticatedRoute' is just a custom made route for logged-in users):
App.Note = DS.Model.extend({
title: DS.attr(),
author: DS.attr(),
body: DS.attr(),
createdAt: DS.attr()
});
App.NotesRoute = App.AuthenticatedRoute.extend({
model: function() { return this.store.find('note'); },
});
App.NotesNewRoute = App.AuthenticatedRoute.extend({
model: function() {
return this.store.createRecord('note');
}
});
App.NotesNewController = Ember.ObjectController.extend({
actions: {
save: function() {
var self = this, model = this.get('model');
model.set('author', localStorage.username);
model.set('createdAt', new Date());
model.save().then(function() {
self.get('target.router').transitionTo('notes.index');
});
}
}
});
When I save a new note everything works as expected. But when I navigate away from the notes route and then back into it, the notes list is populated with a duplicate entry. One entry has an id and can be edited, deleted etc, the other has all the data of the first entry except the id attribute is null. It seems to me ember-data keeps the newly created record (that hasn't been committed to the database and thus has no id yet) alive even when the record becomes committed but I am uncertain as to why. When I reload the page, the list is correctly displayed, no duplicates appear. What am I doing wrong?
For the record, I am using mongodb so I use a custom serializer to convert '_id' attributes to ember-data friendly 'id's, essentially copied from here:
App.NoteSerializer = DS.RESTSerializer.extend({
normalize: function(type, hash, property) {
// normalize the '_id'
var json = { id: hash._id };
delete hash._id;
// normalize the underscored properties
for (var prop in hash) {
json[prop.camelize()] = hash[prop];
}
// delegate to any type-specific normalizations
return this._super(type, json, property);
}
});
I should also mention that this problem existed in ember-data 0.13 as well.
It was a stupid mistake in my RESTful server. I was responding to POST requests with a 204 (empty) response instead of what ember-data expected, that is a 201 ("created") response with the newly created record as the payload. This post made me realize it.
It would be nice though to include this information in the official REST adapter documentation.
That is certainly strange behaviour indeed. Unfortunately I'm not able to explain why you're experiencing this, however:
You can use the willTransition callback in the actions object in your Route to ensure that when it is transitioned away from, if NotesNewController's content property is dirty (i.e. has not been persisted yet), it will have its transaction rolled back.
App.NotesNewRoute = App.AuthenticatedRoute.extend({
model: function() {
return this.store.createRecord('note');
},
actions: {
willTransition: function (transition) {
var model = this.controllerFor('notesNew').get('content');
if (model.get('isDirty') === true) {
model.get('transaction').rollback();
}
return this._super(transition);
}
}
});