ember js - Uncaught Error: Assertion Failed: Cannot delegate set - ember.js

i face this error when saving data to api
Uncaught Error: Assertion Failed: Cannot delegate set('firstName', a) to the 'content' property of object proxy <>: its 'content' is undefined
below is my code
import Ember from 'ember';
export default Ember.ObjectController.extend({
isValid: Ember.computed(
'email',
'firstName',
'lastName',
'twitter',
function() {
return !Ember.isEmpty(this.get('email')) &&
!Ember.isEmpty(this.get('firstName')) &&
!Ember.isEmpty(this.get('lastName')) &&
!Ember.isEmpty(this.get('twitter'));
}
),
actions:{
save: function() {
if (this.get('isValid')) {
var _this = this;
this.get('model').save().then(function(friend) {
_this.transitionToRoute('friends.show', friend);
});
} else {
this.set('errorMessage', 'You have to fill all the fields');
}
},
cancel: function() {
this.transitionToRoute('friends');
}
}
});

Don't use ObjectController. Use simply Ember.Controller.extend.

I see this on the ember-cli-101 book. I encountered the same issue myself. It's likely that you are not properly setting the model attribute in your route. Based on the book, the error either occurs in the edit or new route.
if your router.js looks like this:
...
Router.map(function() {
this.resource('friends', function() {
this.route('new');
this.route('show', { path: ':friend_id' });
this.route('edit', { path: ':friend_id/edit' });
});
});
...
the friends/index route needs to set the model attribute:
import Ember from 'ember';
export default Ember.Route.extend({
model: function() {
return this.store.find('friend');
},
});
and the friends/new route needs to set the model in a different way:
import Ember from 'ember';
export default Ember.Route.extend({
model: function() {
return this.store.createRecord('friend');
},
});
For anyone not familiar with the book (mentioned above) the question is from code that is in the book, which is why I referenced it. In most cases, if you get this issue it is likely because you forgot to or did not set up the model attribute correctly in the appropriate route.

Related

Getting specific item with findRecord

I'm new at ember and as first app I'm trying to build a little online shop.
I can receive "all products" as product overview but not one specific product by id.
I have following in the router.js:
Router.map(function() {
this.route('products');
this.route('product', {path: 'products/:product_id'});
});
My products.js (which works):
import Ember from 'ember';
export default Ember.Route.extend({
model(){
return this.get('store').query('product', {});
}
});
And the product.js (which does generate the problem):
import Ember from 'ember';
export default Ember.Route.extend({
model(params){
return this.store.findRecord('product', params.product_id);
}
});
The project is available under https://github.com/hatchling-shop/hatchling/tree/master/EmberHatchling
After running the code seems that you have an issue in the API in Product.findById() and not in Ember.
In the following method:
Product.findById(id, function(id, err, product) {
if (err) {
res.send(err);
}
res.json({product: product});
});
the params in the callback are wrong, instead you need to remove id and change to:
Product.findById(id, function(err, product) {
if (err) {
res.send(err);
}
res.json({product: product});
});
Hope this helps.

Sharing an Ember Object between controllers with ember-cli

I'm trying to share a Ember object between different controllers in order to 'decorate' it with more information as you go through the app.
In a simple Ember app I would just do:
App.UserDetails = Ember.Object.extend({name: 'Darryl', age: 26 });
App.DetailsRoute = Ember.Route.extend({
model: function () {
return App.UserDetails;
}
});
App.AccountRoute = Ember.Route.extend({
model: function () {
return App.UserDetails;
}
});
But I can't see I would organise this in Ember CLI
Thanks
You should use data persistence library like Ember Data, because it was designed for things like storing user details and there are tons of information how to do that, but you ask about sharing an object so:
You can use Ember.Service:
Details service:
import Ember from 'ember';
export default Ember.Service.extend({
name: 'Darryl',
age: 26
});
Rest:
App.DetailsRoute = Ember.Route.extend({
details: Ember.inject.service(),
model: function () {
return this.get('details');
}
});
App.AccountRoute = Ember.Route.extend({
details: Ember.inject.service(),
model: function () {
return this.get('details');
}
});
The same thing can be done like this,
//userdetails.js
export default Ember.Object.create({
name: 'Darryl',
age: 26
});
In your Routes,
//details.js
import obj from 'path/userdetails';
export default Ember.Route.extend({
model : function(){
return obj;
}
});
//account.js
import obj from 'path/userdetails';
export default Ember.Route.extend({
model : function(){
return obj;
}
});

How to load belongsTo/hasMany relationships in route with EmberJS

In my EmberJS application I am displaying a list of Appointments. In an action in the AppointmentController I need to get the appointments owner, but the owner always returns "undefined".
My files:
models/appointment.js
import DS from 'ember-data';
export default DS.Model.extend({
appointmentStatus: DS.attr('number'),
owner: DS.hasMany('person'),
date: DS.attr('Date')
});
models/person.js
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string')
});
templates/appointmentlist.js
{{#each appointment in controller}}
<div>
{{appointment.date}} <button type="button" {{action 'doIt'}}>Do something!</button>
</div>
{{/each }}
controllers/appointmentlist.js
export default Ember.ArrayController.extend({
itemController: 'appointment'
});
controllers/appointment.js
export default Ember.ObjectController.extend({
actions:{
doIt: function(){
var appointment = this.get('model');
var owner = appointment.get('owner'); //returns undefined
//Do something with owner
}
}
});
Now, I know I can change the owner-property to owner: DS.hasMany('person', {async: true}), and then handle the promise returned from appointment.get('owner');, but that is not what I want.
I have discovered that if I do this {{appointment.owner}} or this {{appointment.owner.name}} in the appointmentlist template, the owner record is fetched from the server. So I guess Ember does not load relationships unless they are used in the template.
I think that the solution to my problem is to use the appointmentlists route to fetch the record in the belongsTo relationship. But I can't figure out how.
Maybe something like this?
routes/appointmentlist.js
export default Ember.Route.extend({
model: function() {
return this.store.find('appointment');
},
afterModel: function(appointments){
//what to do
}
});
EDIT
I did this:
routes/appointmentlist.js
export default Ember.Route.extend({
model: function() {
return this.store.find('appointment');
},
afterModel: function(appointments){
$.each(appointments.content, function(i, appointment){
var owner= appointment.get('owner')
});
}
});
and it works, but I do not like the solution...
You are still asynchronously loading those records, so if you are fast enough you could still get undefined. It'd be better to return a promise from the afterModel hook, or just modify the model hook to do it all.
model: function() {
return this.store.find('appointment').then(function(appointments){
return Ember.RSVP.all(appointments.getEach('owner')).then(function(){
return appointments;
});
});
}
or
model: function() {
return this.store.find('appointment');
},
afterModel: function(model, transition){
return Ember.RSVP.all(model.getEach('owner'));
}
Another way to go is:
export default Ember.Controller.extend({
modelChanged: function(){
this.set('loadingRelations',true);
Ember.RSVP.all(this.get('model').getEach('owner')).then(()=>{
this.set('loadingRelations',false);
});
}.observes('model')
});
This way the transition finishes faster and the relations are loaded afterwards. The loading-state can be observed through loadingRelations.
When there are a lot of relations to load I think this gives a better UX.
You want to load all the assocations in the route, because you want to use Fastboot for search engines and better first time site opened experience.
Holding your assocation loading after primary models are loaded, might not be the best decision.
I am using a syntax to load all assocations in the route:
let store = this.store;
let pagePromise = store.findRecord('page', params.page_id);
let pageItemsPromise = pagePromise.then(function(page) {
return page.get('pageItems');
});
return this.hashPromises({
page: pagePromise,
pageItems: pageItemsPromise
});
And for this.hashPromises I got a mixin:
import Ember from 'ember';
export default Ember.Mixin.create({
hashPromises: function(hash) {
let keys = Object.keys(hash);
return Ember.RSVP.hashSettled(hash).then(function(vals) {
let returnedHash = {};
keys.forEach(function(key) {
returnedHash[key] = vals[key].value;
});
return returnedHash;
});
}
});

how to receive variables sent by transitionToRoute

I read at
http://emberjs.com/guides/controllers/
the following code:
I have a search box and want to send the value of the search box to the SearchController.
App.ApplicationController = Ember.Controller.extend({ // the initial
value of the `search` property search: '',
actions: {
query: function() {
// the current value of the text field
var query = this.get('search');
this.transitionToRoute('search', { query: query });
} } });
How can i get the query parameter in the SearchController and then show it in search.hbs?
I am working with ember- cli.
The router is
import Ember from 'ember';
var Router = Ember.Router.extend({
location: NENV.locationType
});
Router.map(function() {
this.route('search');
});
export default Router;
I set up a route under routes/search.js
export default Ember.Route.extend({
model : function (params) {
console.debug("hi");
return params;
},
setupController: function(controller,model) {
var query = model.query;
console.debug("query is");
console.debug(query);
}
});
When debugging i get an error:
ember More context objects were passed than there are dynamic segments
Thanks,
David
You need to define your search route to be dynamic, so if you change your route definition to something like this
Router.map(function() {
this.resource('search', {path: '/search/:query});
})
This should work as you are expecting. Let me know if anything.
Cheers!

Ember Router rootURL option (Uncaught Error: No route matched the URL '/admin')

I'm trying to start to build a admin system that will run on a /admin/ prefix.
Here is my routes file
App.Router.reopen
location: 'history'
rootURL: '/admin'
App.IndexRoute = Ember.Route.extend
setupController: (controller, model) ->
#controllerFor('application').set('currentRoute', 'home')
When I go to /admin I get the following error:
Uncaught Error: No route matched the URL '/admin'
I'm just starting with emberjs, and my code is based on this serie
Ember version: v1.0.0-pre.4
Ember-data current api revision:: 11
In old-router the 'rootURL' property would have been ignored when resolving routes. In the latest version of ember, rootURL only seems to be used when constructing links. Not sure if this is a bug or oversight. As a workaround, try this instead:
App.Router.map(function() {
this.resource("admin", { path: "/admin" }, function() {
this.route("other");
});
});
App.IndexRoute = Ember.Route.extend({
redirect: function() {
this.transitionTo('admin');
}
});
When talking about routing in emberjs, it depends which version you are using. There was a big API change between 1.0pre2 and 1.0pre3. The docu on www.emberjs.com is already up-to-date for the new API and and easy to understand.
Below a really small example that shows
IndexRoute that automatically redirects to the overview of all members at '/members'.
Dynamic routing based on an ID
Serialization/Deserialization in case that the parameter is not 'id' but something else. In the example below, it is 'refId' (stands for reference ID).
Well, the examle does not really show more than the official documentation. but add-on information is always nice.
So, hope this helps. cheers.
App.Router.map(function() {
this.resource("members", { path: '/members' });
this.resource("member", { path: "/members/:refId" }, function() {
this.route("delete");
});
});
App.IndexRoute = Ember.Route.extend({
redirect: function() {
this.transitionTo('members');
}
});
App.MembersRoute = Ember.Route.extend({
model: function() {
return App.Member.findAll();
}
});
App.MemberRoute = Ember.Route.extend({
model: function(params) {
return App.Member.find(params.refId);
},
// overwrite default serializer (defaults to 'id', member has 'refId')
serialize: function(model) {
return { refId: model.refId };
}
});