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
Related
In my app I have a searchformula with dynamic input fields. The form leads then to the following URL:
/trefferliste/?modulId=1&modus=dokument&identnummer=XXX
my route definition:
this.resource('trefferliste', { 'path' : 'trefferliste/:query' });
until this point it works, but when i refresh the page it says: UnrecognizedURLError
in the trefferliste route I load the data with following statement:
return this.store.find('trefferliste', params.query);
I figured out, that the "?" causes the problem, but I need it for my store find query. So, can someone tell me how to define my route?
UPDATE: Here is a jsbin: http://emberjs.jsbin.com/nesehuxugi
Steps to reproduce the error:
Push the Button > then refresh the page and look into the console!
some additional informations:
DEBUG: Ember : 1.12.1
ember-template-compiler.js:163 DEBUG: Ember Data : 1.0.0-beta.17
ember-template-compiler.js:163 DEBUG: jQuery : 1.11.2
Use query params instead of dynamic segments, so characters with special meaning to URL schema will be escaped and your application routing will work even on refresh.
URL becomes: http://app.com#/trefferliste?query=%3FmodulId%3D1%26modus%3Ddokument%26identnummer%3DXXX, but you have to respect Ember.js and global URL conventions.
Working demo.
Code:
App = Ember.Application.create();
App.Router.map(function() {
this.resource('trefferliste');
});
App.IndexRoute = Ember.Route.extend({
model: function() {
return ['red', 'yellow', 'blue'];
}
});
App.TrefferlisteController = Ember.Controller.extend({
queryParams: ['query'],
query: null
});
App.IndexController = Ember.ObjectController.extend({
actions: {
suche: function() {
var query = "?modulId=1&modus=dokument&identnummer=XXX";
this.transitionTo('trefferliste', { queryParams: { query: query } });
}
}
});
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.
What is the ember-cli best practice to deleteRecord() on a model that belongsTo multiple models? Do I have to manually clean up relationships on the parents?
Migrating from ember to ember-cli I am having new trouble with deleteRecord() for a model 'star' that belongsTo multiple models, 'post' and 'user'. Before moving to ember cli it was working with this solution.
The previous solution's delete action fails in the current ember-cli with errors and never calls the api. TypeError: Cannot read property 'modelFor' of undefined and Uncaught Error: Assertion Failed: TypeError: Cannot read property 'modelFor' of undefined at the line
var inverse = relationship.parentType.inverseFor(name);
// name is the string 'post'
Now I'm starting simple again. Here is a simple example of what I'm trying. Maybe I am missing something with es6, explicit inverses, or using needs:?
http://localhost:4200/post/1
models
// models/star.js
import DS from 'ember-data';
export default DS.Model.extend({
created: DS.attr('date'),
post: DS.belongsTo('post', {
async: true,
inverse: 'stars'
}),
user: DS.belongsTo('user', {
async: true,
inverse: 'stars'
})
});
// models/post.js
import DS from 'ember-data';
export default DS.Model.extend({
headline: DS.attr(),
body: DS.attr(),
stars: DS.hasMany('star', { async: true })
});
// models/users.js
import DS from 'ember-data';
export default DS.Model.extend({
username: DS.attr(),
stars: DS.hasMany('star', { async: true })
});
controller
//controllers/post.js
import Ember from 'ember';
export default Ember.ObjectController.extend({
actions: {
createStar: function(){
var self=this,
post = this.get('model'),
user = this.store.find('user', 2),
star;
user.then( function(user){
star = self.get('store').createRecord('star', {
post: post,
user: user
});
star.save().then( function(star){
post.get('stars').then( function(stars){
stars.pushObject(star);
});
user.get('stars').then( function(stars){
stars.pushObject(star);
});
});
});
},
deleteStar: function() {
var user = this.store.find('user', 2),
self = this;
user.then( function(user){
var filtered = self.get('stars').filterProperty('user.id', user.id);
var star = filtered[0];
star.deleteRecord();
star.save();
});
return(false);
}
}
});
Update: Alternate deleteStar post controller action re: #jjwon
deleteStar: function() {
var user = this.store.find('user', 2),
self = this;
user.then( function(user){
var stars = self.get('stars').then( function(items){
// log the post's stars before delete
items.forEach(function(item) {
console.log(item);
});
var filtered = items.filterBy('user.id', user.id);
var star = filtered.get('firstObject');
star.deleteRecord();
star.save().then(function(){
// log the post's stars after delete
items.forEach(function(item) {
console.log(item);
});
});
});
});
return(false);
}
Interestingly I found that if I add a star, reload the page, then delete it, that the star is successfully removed from the post's stars. Great!
But if I add a star and remove it without reloading, there is still a reference to the removed star with its id among the post's stars. Looking in the console, the removed star object is still referenced by the post with its id, but the user and post attributes are undefined.
stars is an async attribute of user. Therefore, when you have:
var filtered = self.get('stars').filterProperty('user.id', user.id);
var star = filtered[0];
star.deleteRecord();
star.save();
filtered might be a promise, so this might not be working as expected. Also, I'm not too familiar with filterProperty, but you don't have an attribute called user.id so it seems like that might be returning an empty list?
For now I'm cleaning up the relationships on the parents very manually. This works but isn't ideal.
deleteStar: function() {
var user = this.store.find('user', 2),
self = this;
user.then( function(user){
var star = self.get('stars').filterBy('user.id', user.id).get('firstObject');
// clean up relationships on parents very manually
// user.stars
user.get('stars').removeObject(star);
// posts.stars
self.get('stars').removeObject(star);
star.deleteRecord();
star.save();
});
return(false);
}
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.)
In my Emberjs application I have an Employee model which I should load through a REST Get API call, where I have to authenticate the API first for a token then start loading the data, I know how to do this easily using JQuery but not sure how I can implement this in EmberJS, so I will appreciate it so much if anyone can instruct me how to do so.
Below is the JQuery code I use for authentication, extracting the employees data, as well as my EmberJS model code
Thanks
Authentication:
$.ajax
({
type: "POST",
url: "http://portal.domainname.com/auth",
dataType: 'json',
async: false,
data: JSON.stringify({
Login: "logmein#email.com",
Password : "test"
}),
success: function(data) {
console.log(data); //Here I get the token needed for further calls...
},
error: function(xhr, error){
console.debug(xhr); console.debug(error);
}
});
Calls to load employees data:
$.ajax ({
type: "GET",
url: "http://portal.domainname.com/employees",
dataType: 'json',
async: false,
beforeSend: function (xhr) {
xhr.setRequestHeader ("Token", "0000000-0000-0000-0000-00000000");
},
success: function(data) {
console.log(data);
},
error: function(xhr, error){
console.debug(xhr); console.debug(error);
} });
EmberJS Model
App.Store = DS.Store.extend({
revision: 11
});
App.Employee = DS.Model.extend({
employeeID: DS.attr('string'),
employeeName: DS.attr('string')
});
App.Store.reopen({
adapter: 'DS.RESTAdapter'
});
You can add headers to all Ember AJAX requests like this:
App.Store = DS.Store.extend({
revision: 13,
adapter: DS.RESTAdapter.extend({
ajax: function(url, type, hash) {
if (!hash) {
hash = {};
}
hash.beforeSend = function(xhr) {
xhr.setRequestHeader("Authorization", "Token " + window.sessionToken);
};
return this._super(url, type, hash);
}
})
});
I use this code in production.
A very real & viable solution is to avoid using EmberData and just use ajax the way you already know. Take a look at this tutorial from a founder of Discourse (which uses Ember without Ember Data):
http://eviltrout.com/2013/03/23/ember-without-data.html
As a hack you could use something like https://api.jquery.com/jQuery.ajaxPrefilter/ for adding the header with the token to every call. However, I think you should use a dedicated auth library for this.
Also your store has revision: 11 - that is for an old version I believe.
Try something like this:
App.ApplicationAdapter = DS.RESTAdapter.extend({
setHeaders: function() {
this.set('headers', { "Token": "0000000-0000-0000-0000-00000000" });
}.on('init');
});
I think you'll need ember-data-1.0.0-beta.x for this to work.