Ember.js commiting parent model with already existing child models - javascript

Cheers! For example I have three models:
App.Foo = DS.Model.extend({
bars: DS.hasMany('App.Bar', {embedded:'always'}),
bazes: DS.hasMany('App.Baz', {embedded:'always'})
});
App.Bar = DS.Model.extend({
foo: DS.belongsTo('App.Foo')
});
App.Baz = DS.Model.extend({
foo: DS.belongsTo('App.Foo)
});
And adapter mappings like these:
App.RESTSerializer = DS.RESTSerializer.extend({
init: function() {
this._super();
this.map('App.Foo', {
bars:{embedded: 'always'},
bazes:{embedded: 'always'}
})
}
});
I'm saving child records first in separated transactions (github.com/emberjs/data/pull/440):
barTransaction = App.store.transaction();
bar = barTransaction.createRecord(App.Bar);
//later
bazTransaction = App.store.transaction();
baz = bazTransaction.createRecord(App.Baz);
//later
fooTransaction = App.store.transaction();
foo = fooTransaction.createRecord(App.Foo);
//later
foo.get('bars').addObject(bar);
foo.get('bazes').addObject(baz);
fooTransaction.commit();
I just want to know if it possible to save parent and all child records with one POST request?
For now it's creating one POST request for every child record separately.

I believe your issue is with an outdated way of mapping embedded records. This used to happen in the serializer, but is now happening on a map() on the adapter...
You can see the integration test here: https://github.com/emberjs/data/blob/master/packages/ember-data/tests/integration/embedded/embedded_saving_test.js#L50
I think something along these lines will work:
App.Foo = DS.Model.extend({
bars: DS.hasMany('App.Bar'),
bazes: DS.hasMany('App.Baz')
});
App.Bar = DS.Model.extend({
foo: DS.belongsTo('App.Foo')
});
App.Baz = DS.Model.extend({
foo: DS.belongsTo('App.Foo')
});
App.Adapter = DS.RESTAdapter.extend({..configs..});
App.Adapter.map('App.Foo', {
bars:{embedded: 'always'},
bazes:{embedded: 'always'}
})
This should POST to the api at: api.com/foo and include the bars and bazes

Related

live update view in ember

I build application using web-socket and I want dynamically change view
I have code in my model:
model: function () {
var store = this.store;
var socket = new_socket();
socket.on('message', function (message) {
store.push('record',message);
});
return store.find('consultation');
}
And data successfully loading into ember store, but ember doesn't update view.
What I need to do?
For example when I use save all works fine:
var record = this.store.createRecord('record',{});
record.save()
UPDATE:
I found this solution:, but it's also not working
My controller (consultation.js):
export default Ember.ObjectController.extend({
needs: ['application'],
records: function() {
console.log(this.get('store'));
return this.get('store').filter('record', function(record) {
console.log(record);
});
}.property('records'),
Template:
{{#each item in controller.records}}
{{/each}}
Model consultation looks like this (with hasMany field):
export default DS.Model.extend({
records: DS.hasMany('record', { async: true }),
});
Second console.log is not printing,
I solved it like this
var obj = store.push('record', jsonObj.message);
this.controllerFor('consultation').get('records').pushObject(obj);
But it's looks like not good. In which way I can make auto synchronization between model and controller
You have computed properties that are dependent on themselves in your controller. Also, you really should not be pushing anything to the store, conceptually, when you receive something on your socket, your model changed, you want to capture that notion in your code, so you really should be updating the model when you get a socket message. The way I would do this would be to do something like the following:
in the router,
model: function() {
var records = this.store.find('consultation',{});
var socket = new_socket();
socket.on('message', function (message) {
records.pushObject(message);
});
return records;
}
The controller does not need to have any computed properties at all.
and in the template, the code would just be:
{{#each content}}
//do something here
{{/each}}
I'm a little confused about your use of consultation and record in the code.

Ember data store return undefined record from FIXTURES

I am new in ember and i am trying to simply get log of items stored by Fixtures model and i cannot. Here is what I have done:
app.js
App = Ember.Application.create();
App.Store = DS.Store.extend({
adapter: DS.FixtureAdapter.extend()
});
App.Documenter = DS.Model.extend({
firstName: DS.attr('string'),
lastName: DS.attr('string')
});
App.Documenter.FIXTURES = [
{ id: 1, firstName: 'Trek', lastName: 'Glowacki' },
{ id: 2, firstName: 'Tom', lastName: 'Dale' }
];
App.IndexRoute = Ember.Route.extend({
controllerName: 'application',
actions: {
addtostore: function () {
},
displaystore: function () {
var obj = this.store.all('documenter');
console.log(obj.objectAt(0).firstName); //here i get undefined
}
}
});
html:
<script type="text/x-handlebars">
<h2> Ember POC</h2>
<p>POC</p>
{{outlet}}
<button {{action 'displaystore'}}>TestButton</button>
</script>
I've looked at few answers already on stackoverflow:
Ember-Data Fixture Adapter
Ember App Kit with ember data
but still I dont get, why button TestButton dont log into console. I tried many ways but always it is undefined
No need to define the store, and your adapter should be defined like so:
App.ApplicationAdapter = DS.FixtureAdapter;
And all only returns records that have already been found and are in the store. The FIXTURES hash isn't automatically loaded into the store, you still need to use find in order to get records from the FIXTURES hash.
displaystore: function () {
this.store.find('documenter').then(function(records){ // this is async
console.log(records.get('firstObject.firstName'));
});
}
It's doubtful you would want to call find from the action like this, since it'd call back to the server each time, generally you'd get the records in the route (or even prime your store in the route so you can use all).
Because I am fresh in Ember, I made few common mistakes. I did not understand routes, handlebars, etc., and I messed up. The problem was that I did not assign the model to a controller.
App.IndexRoute = Ember.Route.extend({
model: function () {
var store = this.get('store');
return store.findAll('documenter');
}
});

Ember custom JSON

Im having a hard time figuring out how i would tell Ember to serialize this json example
{
"error":false,
"data":{
"total":1,
"per_page":15,
"current_page":1,
"last_page":1,
"from":1,
"to":1,
"data":[
{
"id":"11",
"type":"1",
"body":"a simple body",
"owner":"14",
"published":"1",
"updated_at":"2013-12-10 14:30:31",
"created_at":"2013-12-10 14:30:31"
}
]
}
}
I can't figure out how to tell Ember that the data which is loaded from /feedItems are inside data and then data,
I have tried multiple things but can't grasp it, so far i have this in my app.js:
App.FeedItem = DS.Model.extend({
error: DS.attr('boolean'),
data: DS.hasMany('FeedItemData')
});
App.FeedItemData = DS.Model.extend({
data: DS.hasMany('FeedItemDataData')
});
App.FeedItemDataData = DS.Model.extend({
body: DS.attr('string')
});
App.FeedRoute = Ember.Route.extend({
model: function(params) {
return this.store.find('FeedItem');
}
});
Your current approach is incorrect. Models should represent the way your data ought to look, no the way that it is returned from the server. FeedItemData and FeedItemDataData are not logical entities in your application and therefore should not exist.
You need to create FeedItemSerializer (or ApplicationSerializer if all your data is formatted this way) that would look something like this:
FeedItemSerializer = Ember.RESTSerializer.extend({
normalizePayload: function(type, payload) {
if(!payload.error) {
return payload.data.data;
} else {
// handle the error
}
}
});
Or alternatively do something similar in extractArray as documented here.

Models are not serialized with Ember.js and WebApiAdapter

I'm trying to use the Ember.js MVC4 Spa Template with my own Models, but I'm not getting this to work.
For now, the serverside code is is working. The result to the browser is correct. But Ember-Data, or the custom WebApi - Serializer, is not able to prepare the Data.
I have two Models:
Patient:
App.Patient = DS.Model.extend();
App.Patient.reopen({
patientId: DS.attr('number'),
firstName: DS.attr('string'),
lastName: DS.attr('string'),
aufenthalte: DS.hasMany('aufenthalt'), //, { async: true }
fullName: function () {
return this.get('firstName') + ' ' + this.get('lastName');
}.property('firstName', 'lastName'),
});
App.PatientSerializer = DS.WebAPISerializer.extend({
primaryKey: 'patientId',
// ember-data-1.0.0-beta2 does not handle embedded data like they once did in 0.13, so we've to update individually if present
// once embedded is implemented in future release, we'll move this back to WebAPISerializer.
// see https://github.com/emberjs/data/blob/master/TRANSITION.md for details
extractArray: function (store, primaryType, payload) {
var primaryTypeName = primaryType.typeKey;
var typeName = primaryTypeName,
type = store.modelFor(typeName);
var data = {};
data[typeName] = payload;
data.aufenthalte = [];
var normalizedArray = payload.map(function (hash) {
hash.aufenthalte.map(function (aufenthalt) {
data.aufenthalte.push(aufenthalt);
});
hash.aufenthalte = hash.aufenthalte.mapProperty('aufenthaltId');
return hash;
}, this);
payload = data;
return this._super.apply(this, arguments);
},
normalizeHash: {
patient: function (hash) {
hash.patientId = hash.id;
return hash;
}
}
});
Aufenthalt:
App.Aufenthalt = DS.Model.extend({
aufenthaltId: DS.attr('number'),
name: DS.attr('string'),
patientId: DS.attr('number'),
patient: DS.belongsTo('patient'),
});
App.AufenthaltSerializer = DS.WebAPISerializer.extend({
primaryKey: 'aufenthaltId',
normalizeHash: {
aufenthalte: function (hash) {
hash.aufenthaltId = hash.id;
return hash;
},
}
});
When I get a List of "Patients" from my Controller, the Datamodels are filled correctly (I can check it in the Chrome Ember plugin.) When I hit a Action with the Patient Id, I get the error: "Error while loading route: TypeError: Cannot set property 'store' of undefined"
Thank You!
Did you added the proper router in app/routes folder, controller in app/controllers folder, and corresponding views and templates? Feel free to psot a link to your sample solution so I can download and have a look.
=== Update 2/22/2014 ===
I fixed the code. You should be able to download the modified solution from https://www.dropbox.com/s/4j3vbczqr4nx68m/EmberVSTemplateModified.zip. You should do a windiff on the two directories to see the changes. I need to change a few places to make it work for your scenario, including:
patient.js, make it directly extend from RESTSerialzer, and add extractSingle implementation.
change template of patsucheautocomplete.hbs
added patient\index.hbs . You should be able to remove patient.hbs file
paitentview.js (may not be necessary as it's all default)
modified controllers\htmlhelperextensions.cs, to make it work correctly for sub folder templates in debug mode.

Adding new feature to discourse

I am trying to add an WatchList feature in the existing code discourse ember rails application
I have addded the following code
Discourse.Route.buildRoutes(function() {
var router = this;
this.resource('watchLists', { path: '/watch_lists' }, function() {
this.resource('watchList', {path: ':watch_list_id'});
});
});
In the ember Controller
Discourse.WatchListsController = Discourse.ObjectController.extend({});
In the ember model
Discourse.WatchList = Discourse.Model.extend({});
Discourse.WatchList.reopenClass({
find: function() {
jQuery.getJSON("watch_lists").then(function(json) {
var watch_lists = json.watch_lists.map(function(attrs) {
return Discourse.WatchList.create(attrs);
});
});
In the ember view js
Discourse.WatchListsView = Ember.View.extend({});
In ember route js
Discourse.WatchListsRoute = Discourse.Route.extend({
model: function() {
return Discourse.WatchList.find();
}
});
When i renderring the handlebars template I am getting an WatchListsController object withot the data we have got from the ajax.
Can any body point out where i am doing wrong.
I see two possible problems.
First, you probably want WatchListsController to extend Discourse.ArrayController, not Discourse.ObjectController.
Second your reopen block is not valid JavaScript in the example code that you posted. I count four { but only two }. You probably want something kind of like this:
Discourse.WatchList.reopenClass({
find: function() {
return jQuery.getJSON("watch_lists").then(function(json) {
return json.watch_lists.map(function(attrs) {
return Discourse.WatchList.create(attrs);
}
});
}
});

Categories

Resources