Controller is defined, but can not be found - ember.js

When trying to get the nodeEditController from nodeController:startEditing, I get the following problem:
Uncaught TypeError: Cannot call method 'set' of undefined
This is the NodeController:
SettingsApp.NodeController = Ember.ObjectController.extend({
isEditing: false,
startEditing: function () {
debugger;
var nodeEditController = this.get('controllers.nodeEdit');
nodeEditController.set('content', this.get('content'));
nodeEditController.startEditing();
this.set('isEditing', true);
},
...
This is the NodeEditController:
SettingsApp.NodeEditController = Ember.ObjectController.extend({
needs: ['node'],
startEditing: function () {
//debugger;
// add the contact and its associated phone numbers to a local transaction
var node = this.get('content');
var transaction = node.get('store').transaction();
transaction.add(node);
// contact.get('phones').forEach(function (phone) {
// transaction.add(phone);
// });
this.transaction = transaction;
},
...
The error happens in line:
nodeEditController.set('content', this.get('content'));
Because:
var nodeEditController = this.get('controllers.nodeEdit');
Returns undefined. Why is that? The NodeEditController is defined!

The NodeController is missing the needs property:
SettingsApp.NodeController = Ember.ObjectController.extend({
needs : ["nodeEdit"],
isEditing: false,
startEditing: function () {
debugger;
var nodeEditController = this.get('controllers.nodeEdit');
nodeEditController.set('content', this.get('content'));
nodeEditController.startEditing();
this.set('isEditing', true);
},
...

Related

Emberjs - how to reset a field on a component after saving?

I have an embedded object called Comment, inside a Game. Each game can have many Comments.
When a user (called a Parent) views the game page, they can leave a comment.
The problem I have is that I cannot seem to reset the body of the comment field back to empty after the comment is saved.
This is the component:
MyApp.AddCommentComponent = Ember.Component.extend({
body: '',
actions: {
addComment: function() {
var comment, failure, success;
if (!!this.get('body').trim()) {
comment = this.store.createRecord('comment', {
body: this.get('body'),
game: this.get('game'),
parent_id: this.get('parent_id'),
parent_name: this.get('parent_name')
});
success = (function() {
this.set('body', '');
});
failure = (function() {
return console.log("Failed to save comment");
});
return comment.save().then(success, failure);
}
}
}
});
The error is on the 'this.set' line - this.set is not a function
All the examples I find are about doing this in a controller or by creating a new record upon route change (but the route is not changing in my example, since it is just adding another embedded object to the existing page).
You are using
this.set('body', '');
in success, but the scope of this here is changed, you need to keep the controller scope and set the body to empty string like
MyApp.AddCommentComponent = Ember.Component.extend({
body: '',
actions: {
addComment: function() {
var that = this;
var comment, failure, success;
if (!!this.get('body').trim()) {
comment = this.store.createRecord('comment', {
body: this.get('body'),
game: this.get('game'),
parent_id: this.get('parent_id'),
parent_name: this.get('parent_name')
});
success = (function() {
that.set('body', '');
});
failure = (function() {
return console.log("Failed to save comment");
});
return comment.save().then(success, failure);
}
}
}
});
When you introduce a function, you must remember that the value for this is not (necessarily) the same as the enclosing scope's value for this. Save the reference to the Component to use in a closure, like this:
MyApp.AddCommentComponent = Ember.Component.extend({
body: '',
actions: {
addComment: function() {
var comment, failure, success;
var self= this;
if (!!this.get('body').trim()) {
comment = this.store.createRecord('comment', {
body: this.get('body'),
game: this.get('game'),
parent_id: this.get('parent_id'),
parent_name: this.get('parent_name')
});
success = (function() {
self.set('body', '');
});
failure = (function() {
return console.log("Failed to save comment");
});
return comment.save().then(success, failure);
}
}
}
});

store.updateRecord is not a function in ember.js

I am newbie to ember.js, I am using ember-1.9.1.js and ember-data for my project.
For back-end configuration I have created a REST API with core php and the db is MySQL.
Now I can create new records (posts) from client side using with DS.RESTAdapter's "createRecord" function.
But I don't know how to update a Record (post) with DS.RESTAdapter's "updateRecord" function.
When I try to call the "updateRecord" function from "App.PostController (doneEditing)" I got this error:
Uncaught TypeError: store.updateRecord is not a function --------- app.js
app.js code below
App = Ember.Application.create();
App.IndexRoute = Ember.Route.extend({
redirect: function() {
this.transitionTo('home');
}
});
App.ApplicationAdapter = DS.RESTAdapter.extend({
namespace: 'pran/webapp/rest_adapter/api',
createRecord: function(store, type, snapshot) {
var data = this.serialize(snapshot, { includeId: true });
var url = "api/new_post";
return new Ember.RSVP.Promise(function(resolve, reject) {
jQuery.ajax({
type: 'POST',
url: url,
dataType: 'json',
data: data
}).then(function(data) {
Ember.run(null, resolve, data);
}, function(jqXHR) {
jqXHR.then = null; // tame jQuery's ill mannered promises
Ember.run(null, reject, jqXHR);
});
});
},
updateRecord: function(store, type, snapshot) {
var data = this.serialize(snapshot, { includeId: true });
var id = snapshot.id;
var url = [type, id].join('/');
return new Ember.RSVP.Promise(function(resolve, reject) {
jQuery.ajax({
type: 'PUT',
url: url,
dataType: 'json',
data: data
}).then(function(data) {
Ember.run(null, resolve, data);
}, function(jqXHR) {
jqXHR.then = null; // tame jQuery's ill mannered promises
Ember.run(null, reject, jqXHR);
});
});
}
});
App.Store = DS.Store.extend({
revision: 12,
adapter: 'App.ApplicationAdapter'
});
App.Post = DS.Model.extend({
title: DS.attr('string'),
author: DS.attr('string'),
date: DS.attr('date'),
excerpt: DS.attr('string'),
body: DS.attr('string')
});
App.Router.map(function() {
this.resource('home');
this.resource('about');
this.resource('posts', function(){
this.resource('post', { path: ':post_id' });
});
this.resource('newstory' , {path : 'story/new'});
});
App.PostsRoute = Ember.Route.extend({
model: function() {
return this.store.filter('post', { id: true }, function(post) {
return post.get('id');
return this.store.find('post');
});
}
});
App.PostRoute = Ember.Route.extend({
model: function(params) {
return this.store.find('post', params.post_id);
}
});
App.NewstoryController = Ember.ObjectController.extend({
actions :{
save : function(){
var title = $('#title').val();
var author = $('#author').val();
var excerpt = $('#excerpt').val();
var body = $('#body').val();
var store = this.get('store');
var new_post = store.createRecord('post',{
title : title,
author : author,
date : new(Date),
excerpt : excerpt,
body : body
});
new_post.save();
this.transitionToRoute('posts');
}
}
});
App.PostController = Ember.ObjectController.extend({
isEditing: false,
actions: {
edit: function() {
this.set('isEditing', true);
},
doneEditing: function() {
this.set('isEditing', false);
var title = $('#title').val();
var excerpt = $('#excerpt').val();
var body = $('#body').val();
var store = this.get('store');
var update_post = store.updateRecord('post',{
title : title,
excerpt : excerpt,
body : body
});
update_post.save();
}
}
});
Somebody please suggest a way to fix the issue.
updateRecord is adapter's method not store's
so try next:
store.adapterFor(App.Post).updateRecord(...
this is fast fix
And better create Post object and call method .save() - it's not good practice to work with adapter from controller like
App.Post.create({
title : title,
excerpt : excerpt,
body : body
}).save();
P.S. The final solution was
App.NewstoryController = Ember.ObjectController.extend({
actions :{
save : function(){
var title = $('#title').val();
var author = $('#author').val();
var excerpt = $('#excerpt').val();
var body = $('#body').val();
var store = this.get('store');
var new_post = store.createRecord('Post',{
title : title,
author : author,
date : new(Date),
excerpt : excerpt,
body : body
});
new_post.save();
this.transitionToRoute('posts');
}
}
});

Delay ember view render till $getJSON isLoaded

The problem with this code is that the render code is entered twice, and the buffer is not where I expect it. Even when I get the buffer, the stuff I push in is not rendered to the screen.
App.FilterView = Ember.View.extend({
init: function() {
var filter = this.get('filter');
this.set('content', App.ViewFilter.find(filter));
this._super();
},
render: function(buffer) {
var content = this.get('content');
if(!this.get('content.isLoaded')) { return; }
var keys = Object.keys(content.data);
keys.forEach(function(item) {
this.renderItem(buffer,content.data[item], item);
}, this);
}.observes('content.isLoaded'),
renderItem: function(buffer, item, key) {
buffer.push('<label for="' + key + '"> ' + item + '</label>');
}
});
And the App.ViewFilter.find()
App.ViewFilter = Ember.Object.extend();
App.ViewFilter.reopenClass({
find: function(o) {
var result = Ember.Object.create({
isLoaded: false,
data: ''
});
$.getJSON("http://localhost:3000/filter/" + o, function(response) {
result.set('data', response);
result.set('isLoaded', true);
});
return result;
}
});
I am getting the data I expect and once isLoaded triggers, everything runs, I am just not getting the HTML in my browser.
As it turns out the answer was close to what I had with using jquery then() on the $getJSON call. If you are new to promises, the documentation is not entirely straight forward. Here is what you need to know. You have to create an object outside the promise - that you will return immediately at the end and inside the promise you will have a function that updates that object once the data is returned. Like this:
App.Filter = Ember.Object.extend();
App.Filter.reopenClass({
find: function(o) {
var result = Ember.Object.create({
isLoaded: false,
data: Ember.Object.create()
});
$.getJSON("http://localhost:3000/filter/" + o).then(function(response) {
var controls = Em.A();
var keys = Ember.keys(response);
keys.forEach(function(key) {
controls.pushObject(App.FilterControl.create({
id: key,
label: response[key].label,
op: response[key].op,
content: response[key].content
})
);
});
result.set('data', controls);
result.set('isLoaded', true);
});
return result;
}
});
Whatever the function inside then(), is the callback routine that will be called once the data is returned. It needs to reference the object you created outside the $getJSON call and returned immediately. Then this works inside the view:
didInsertElement: function() {
if (this.get('content.isLoaded')) {
var model = this.get('content.data');
this.createFormView(model);
}
}.observes('content.isLoaded'),
createFormView: function(data) {
var self = this;
var filterController = App.FilterController.create({ model: data});
var filterView = Ember.View.create({
elementId: 'row-filter',
controller: filterController,
templateName: 'filter-form'
});
self.pushObject(filterView);
},
You can see a full app (and bit more complete/complicated) example here

Emberjs - setProperties from a Promise

I'm trying to set a variable in my router from the inside of a promise, but it seems that it is not set properly.
I have create a small example to show you :
App.ApplicationRoute = Ember.Route.extend({
myVar: null,
model: function() {
var data = getData();
console.log(myVar); // = null
return data;
},
getData: function() {
var self = this;
return new Ember.RSVP.Promise( function(resolve, reject) {
self.setProperties({ myVar: 42 });
resolve(someGoodStuff);
reject(someBadStuff)
});
}
})
When I try to display myVar, it still at null even when it was waiting for the promise to resolve...
Do I need to do something special ? or I'm doing it wrongly ?
I believe you are looking for something like this: http://emberjs.jsbin.com/gosoj/3/edit?html,css,js,output
I'm not entirely sure what you are going for here, so there is also some other commented code that may have been your intention.
I think maybe the problem was when you were console logging, as well as the fact that you weren't using your getters and setters properly, and the way you were calling getData()
Here is the code:
App.ApplicationRoute = Ember.Route.extend({
myVar: null,
model: function() {
var data = this.getData();
console.log(data);
console.log(this.get('myVar')); // = null
return data;
},
getData: function() {
var self = this;
return new Ember.RSVP.Promise( function(resolve, reject) {
self.setProperties({ myVar: 42 });
resolve(42);
reject(reason);
}).then(function (value) {
//self.setProperties({ myVar: value });
console.log(self.get('myVar'));
}, function(reason){
console.log(reason);
});
}
})

Uncaught TypeError: Object #<Object> has no method 'set'

When i try set my 'content' to the customerList i'll get the error:
Uncaught TypeError: Object #Object has no method 'set'
Here is my code:
App.TableController = Em.ArrayController.extend({
init: function() {
this._super();
this.getData();
},
getData: function() {
$.get('data/customer.json', function(data) {
var customerList = Ember.A([]);
data.forEach(function(item) {
var customer = App.overv.create({
incidient: item.incidient,
customer: item.customer,
machine: item.machine,
priority: item.priority
});
customerList.pushObject(customer);
});
this.set('content', customerList);
});
}});
I I also tried it with App.router.tableController.set('content',customerList) but ember doesn't recognize the controller anymore. With 1.0.0 pre 2 this second example worked great.
Now i try to figure out what i did wrong or probably understood wrong.
Keep a reference of this in a local variable _self. See code below.
App.TableController = Em.ArrayController.extend({
init: function() {
this._super();
this.getData();
},
getData: function() {
var _self = this;
$.get('data/customer.json', function(data) {
var customerList = Ember.A([]);
data.forEach(function(item) {
var customer = App.overv.create({
incidient: item.incidient,
customer: item.customer,
machine: item.machine,
priority: item.priority
});
customerList.pushObject(customer);
});
_self.set('content', customerList);
});
}});
probably just an issue with the context of the AJAX callback... you could try this:
App.TableController = Em.ArrayController.extend({
init: function() {
this._super();
this.getData();
},
getData: function() {
$.ajax({
url: 'data/customer.json',
dataType: 'json',
context: this
}).success(function(data, textStatus, jqXHR) {
var customerList = Ember.A([]);
data.forEach(function(item) {
var customer = App.overv.create({
incidient: item.incidient,
customer: item.customer,
machine: item.machine,
priority: item.priority
});
customerList.pushObject(customer);
});
this.set('content', customerList);
});
}
});
specifying TableController as the context to the callback.