I'm quit new into the world of the Adapter in Ember, and I would like to create a custom one to save some data into the webSQL database for the compatible browser.
It might look very simple but I'm stuck at the beginning of this process.
I have this in a separate file :
DS.WebSQLAdapter = DS.Adapter.extend({
dbName: 'testDb',
dbVersion: '1.0',
dbDisplayName: 'Test Db',
dbSize: (2 * 1024 * 1024),
init: function() {
this.db = cont.openDatabase( this.dbName, this.dbVersion, this.dbDisplayName, this.dbSize );
},
createRecord: function( store, type, query, recordArray ) {
console.log(data);
}
})
In my app.js file :
window.App = Ember.Application.create({});
App.ApplicationAdapter = DS.WebSQLAdapter;
And when I do this in my controller :
App.ApplicationController = Ember.ArrayController.extend({
actions: {
myAction: function() {
this.store.createRecord('someDB', {key: 'test', title: 'myTitle'});
}
}
})
It says that it couldn't found the model someDB.. Do I need to create a model as well for my adapter even though I'm using websql to fetch the data ?
It's telling you that SomeDB doesn't exist. Ember is expecting the following to be in your code somewhere:
App.SomeDB = DS.Model.extend({});
If you don't declare a SomeDB model, you can't create a new record of that type. (At least not with the Ember-Data store.)
Related
I am trying to push the updated model back to store. i tried with couple of ways still getting failed.
Please help me to understand to push the model back to store without updating backend api.
here is my try:
import Ember from 'ember';
export default Ember.Route.extend({
model: function(params) {
if(this.store.hasRecordForId('card-list', params.id)){
return this.store.peekRecord('card-list', params.id );
}
},
actions:{
formValidateBeforeNext:function(){
var model = this.controllerFor(this.routeName).get('model');
var modelId = this.controllerFor(this.routeName).get('model').get("id");
var oneTimeFee = this.controllerFor(this.routeName).get('model').get("oneTimeFee");
var monthlyInstalmentAmount = this.controllerFor(this.routeName).get('model').get("monthlyInstalmentAmount");
var updatedModel = JSON.parse(JSON.stringify(model));
updatedModel.type="card-list";
updatedModel.id="13";
console.log( "model would be:-" , updatedModel );
//sending just a updated model fails
let itemModel = this.store.push({'card-list': model });
//after stringfy trying to update still fails
let itemModel = this.store.push({'data': updatedModel });
// this.store.pushObject(JSON.parse(JSON.stringify(model)));
console.log( "store data", this.store.peekRecord('card-list', modelId ) )
this.transitionTo('cs2i.balance.balanceReview', {id:modelId});
}
}
});
What is wrong here? what is the correct way to put back the mode with updates?
UPDATE:Error added
Expected an object in the 'data' property in a call to 'push' for undefined, but was instance
Error
push method will expect the data in the expected format. for eg, if you are using the JSONAPI. the below is the expected one.
store.push({
data: {
// primary data for single record of type `Person`
id: '1',
type: 'person',
attributes: {
firstName: 'Daniel',
lastName: 'Kmak'
}
}
});
You can convert json payload into the expected form by doing so,
store.push(store.normalize('person', data));
If you are having raw JSON data, then you can try pushPayload.
this.get('store').pushPayload('card-list',data);
Refer EmberData Model Maker to know expected result format.
Read ember guides models/pushing-records-into-the-store
Read push API doc
Read pushPayload doc -
currently I'm changing my project from ember to ember-cli and run in a issue I can't get rid of. I am really not sure where the problem is, since I also updated ember and ember-data.
I get the Error:
Uncaught Error: Cannot re-register: `store:main`, as it has already been resolved.
I'm trying to load a user via the simple-auth Session.
import UserSession from '../session/user';
export default {
name: 'user-session',
before: 'simple-auth',
after: 'store',
initialize: function(container, application) {
container.register('session:user', UserSession);
}
};
and the session:
import Session from 'simple-auth/session';
export default Session.extend({
setup: function(authenticator, content, trigger) {
// Do not let setup trigger
this._super.call(this, authenticator, content, false);
// Lookup user and trigger events ourselves
var store = this.container.lookup('store:main');
console.log(store.find);
var self = this;
store.find('user', content.userId)
.then(function(user) {
self.set('user', user);
self.trigger('sessionAuthenticationSucceeded');
}, function() {
console.log('ERROR: Could not resolve user of session!');
});
}
});
the store.find is there but then the error breaks it.
I also tired to inject the store like this:
Ember-Simple-Auth currentUser example help required but had the same result.
Further I tried to make it via the instance-initalizer for ember-data beta.19.
I do stuff like this:
Session from '../session/user';
export default {
name: 'user-session1',
after: 'ember-data',
initialize: function(container, application) {
var store = container.lookup('store:main');
}
};
but this ends up in:
Uncaught TypeError: container.lookup is not a function
Using:
DEBUG: -------------------------------
ember.debug.js:4874DEBUG: Ember : 1.12.1
ember.debug.js:4874DEBUG: Ember Data : 1.0.0-beta.19.2
ember.debug.js:4874DEBUG: jQuery : 1.11.3
ember.debug.js:4874DEBUG: Ember Simple Auth : 0.8.0
ember.debug.js:4874DEBUG: -------------------------------
Thx for the help
------------------ EDIT --------------------------------------------
I updated my instance-initializers based on #Artych comment where I get the store.
I removed the custom session from simple-auth and tried it with reopening
ENV['simple-auth'] = {
//session: 'session:user', ...
My function:
initialize: function(application) {
var store = application.container.lookup('store:main');
Session.reopen({
setCurrentUser: function() {
console.log('never get here');
var accessToken = this.get('access_token');
var self = this;
if (!Ember.isEmpty(accessToken)) {
//never gets here, doesn't matter if I take other variables
}
}.observes('access_token', 'id', 'userId', 'user_id')
});
}
the problem now is that it never goes into "setCurrentUser". I still can logout and in. my autenticator:
authenticate: function(credentials) {
return new Ember.RSVP.Promise(function(resolve, reject) {
var ttl = 30*60*1000; // Request login for 30 minutes
var data = _.extend(credentials, {ttl: ttl});
Ember.$.ajax({
type: 'POST',
url: ENV.api + '/users/login',
data: data,
dataType: 'json'
})
.then(function(response) {
console.log(response);
Ember.run(null, resolve, response);
}, function(xhr, status, error) {
Ember.run(null, reject, error);
});
});
},
returns:
Object {id: "xI3sPSsgdOiHLd8DcFyuOE42KhbuO8gi8BjWBJRrgHgeCESWoma99C2RtvC6tnxG", ttl: 1800000, created: "2015-07-02T14:00:06.600Z", userId: 1}
As you can see, I added a bunch of observed variables: observes('access_token', 'id', 'userId', 'user_id') which I saw in different other questions but nothings helps.
Any idea on this?
Thx
I Solved it.
Simple don't use Ember Data 1.0.0-beta.19.2. I upgraded to 1.13.4 and I was able to get the store like before.
I try to model an ajax call via mockjax for ember data.
my models:
App.Service = DS.Model.extend({
name: DS.attr('string'),
service_prices: DS.hasMany('servicePrice')
});
App.ServicePrice = DS.Model.extend({
unit_price: DS.attr('number'),
qty_unit: DS.belongsTo('qtyUnit'),
service: DS.belongsTo('service')
});
App.QtyUnit = DS.Model.extend(Ember.Validations.Mixin, {
name: DS.attr('string'),
});
App.Order = DS.Model.extend({
service: DS.belongsTo('service'),
qty_unit:DS.belongsTo('qtyUnit'),
});
I try to load an order record via mockjax. (Push the button.) According to the console after the call
MOCK GET: /orders/1
Object {url: "/orders/1", type: "GET", isLocal: false, global: true, processData: true…}
Ember data tries a 2nd call
GET http://run.jsbin.com/services/%3CApp.Service:ember518:1%3E 404 (Not Found)
First of all i dont understend why is the 2nd call? Service is sideloaded in my order JSON
var order = {
"order" : {"id":1,"service":1,"qty_unit":4},
"service":[{"id":1,"name":"ENG-GER","service_prices":[1,2]}],
"servicePrices":[
{"id":1,"qty_unit":4,"unit_price":3},
{"id":2,"qty_unit":5,"unit_price":4}
],
"qtyUnits":[
{"id":4,"name":"character"},
{"id":5,"name":"word"},
{"id":6,"name":"sentence"}
]
};
And why tries ember-data call the record App.Service:ember518:1 instead of its id "1"?
Here is the JsBin
http://jsbin.com/finahuna/1/edit
The problem was your setQtyUnits method. You were passing service model rather than just id as expected by your mock endpoint. ember518 is the ember generated name of service model instance in this case which was getting passed rather than id. Modified method is -
setQtyUnits:function(){
var service_id = this.get('model.order.service.id');
if (service_id !== null)
{
var self = this;
//find returns a promise
this.store.find('service',service_id).then(function(service){
//on success
var servicePrices = service.get('service_prices');
var qtyUnits = servicePrices.mapBy('qty_unit');
console.log(qtyUnits);
self.set('qtyUnits', qtyUnits);
});
} else {
this.set('qtyUnits', null);
}
}.observes('model.order.service')
Here is the modified bin - http://jsbin.com/finahuna/4/edit
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);
}
}
});
I am looking for a guide that will help me understand syncing models in ember. I tried to use the RestAdapter on the latest build and I am getting an error. So I decided to use the BasicAdapter based on stabilizing ember data on the ember js site.
Here is my model:
App.Accounts = DS.Model.extend({
name:DS.attr('string')
,date:DS.attr('date')
})
Here is where I declare the sync functions for the model.
App.Accounts.sync = {
list: function() {
$.ajax({
type: 'POST',
cache: false,
url: contextPath + 'account/list',
success: function(data) {
this.load()
},
error: function(jqXHR, textStatus, errorThrown) {
},
async: false
});
}
}
I am calling the list function in a setup controller:
App.TestRoute = Ember.Route.extend({
setupController:function(){
App.Accounts.list()
}
})
The function does not execute. What is the correct way to call sync functions in an ember application? Also, I could use a blog/article on this topic.
Thanks!
Have you checked out Ember Model it gives you a basic adapter without having to use EmberData.
Erik has a tutorial at embercasts.com you may need to signup to be beta user.
var attr = Ember.attr;
App.User = Ember.Model.extend({
id: attr(),
name: attr()
});
App.User.url = "/users";
App.User.adapter = Ember.RESTAdapter.create();
var newUser = App.User.create({name: "Erik"});
newUser.save(); // POST to /users.json
var existingUser = App.User.find(1); // GET /users/1.json
existingUser.set('name', 'Kris');
existingUser.get('isDirty'); // => true
existingUser.save(); // PUT /users/1.json
Cheers