I'm trying to write the Todo app (using ember-cli). When I added active and complete routes underneath my todos resource my item controller stopped working. Before I was using itemController in my Array controller to set my Object controller.
router.js
import Ember from 'ember';
var Router = Ember.Router.extend({
location: TodoMVCENV.locationType });
Router.map(function() {
this.resource('todos', { path: '/' }, function() {
this.route('active');
this.route('complete');
});
});
export default Router;
controllers/todos.js
import Ember from 'ember';
var TodosController = Ember.ArrayController.extend({
actions: {
createTodo: function() {
// Get the todo title set by the "New Todo" text field
var title = this.get('newTitle');
// Create the new Todo model
var todo = this.store.createRecord('todo', {
title: title,
isCompleted: false
});
// Clear the "New Todo" text field
this.set('newTitle', '');
// Save the new model
todo.save();
}
},
itemController: 'todo',
allAreDone: function(key, value) {
if (value === undefined) {
return this.get('length') > 0 && this.everyProperty('isCompleted', true);
}
else {
this.setEach('isCompleted', value);
this.invoke('save');
return value;
}
}.property('@each.isCompleted'),
hasCompleted: function() {
return this.get('completed') > 0;
}.property('completed'),
completed: function() {
return this.filterBy('isCompleted', true).get('length');
}.property('@each.isCompleted'),
remaining: function() {
return this.filterBy('isCompleted', false).get('length');
}.property('@each.isCompleted'),
inflection: function() {
var remaining = this.get('remaining');
return (remaining === 1) ? 'item' : 'items';
}.property('remaining')
});
export default TodosController;
controllers/todo.js
import Ember from 'ember';
var TodoController = Ember.ObjectController.extend({
actions: {
editTodo: function() {
this.set('isEditing', true);
},
acceptChanges: function() {
// Remove is editing property
this.set('isEditing', false);
// If the todo is empty, delete it
// otherwise save it with the new title
if(Ember.isEmpty(this.get('model.title'))) {
this.send('removeTodo');
} else {
this.get('model').save();
}
},
removeTodo: function() {
var todo = this.get('model');
todo.deleteRecord();
todo.save();
}
}
});
export default TodoController;
Before I added my nested routes, the actions in todo.js worked, now I when I try any of the actions in todo.js I get the following in the console:
Uncaught Error: Nothing handled the action 'editTodo'. If you did handle the action, this error can be caused by returning true from an action handler in a controller, causing the action to bubble.
Adding the templates below from comments....
templates/todos.hbs
{{input type="text" id="new-todo" placeholder="What needs to be done?"
value=newTitle action="createTodo"}}
{{outlet}}
<footer id="footer">
<span id="todo-count">
<strong>{{remaining}}</strong> {{inflection}} left
</span>
<ul id="filters">
<li>
{{#link-to "todos.index" activeClass="selected"}}All{{/link-to}}
</li>
<li>
{{#link-to "todos.active" activeClass="selected"}}Active{{/link-to}}
</li>
<li>
{{#link-to "todos.complete" activeClass="selected"}}Active{{/link-to}}
</li>
</ul>
<button id="clear-completed">
Clear completed (1)
</button>
</footer>
templates/todos/index.hbs
<section id="main">
<ul id="todo-list">
{{#each}}
<li {{bind-attr class="isCompleted:completed isEditing:editing"}}>
{{#if isEditing}}
{{input type="text" class="edit" value=title focus-out="acceptChanges"
insert-newline="acceptChanges"}}
{{else}}
{{input type="checkbox" checked=isCompleted class="toggle"}}
<label {{action "editTodo" on="doubleClick"}}>{{title}}</label>
<button {{action "removeTodo"}} class="destroy"></button>
{{/if}}
</li>
{{/each}}
</ul>
</section>
Change your template to:
{{#each todo in content itemController="todo"}}
{{#with todo}}
...
{{/with}}
{{/each}}
I added the {{with}} block due to the updates in Ember 1.6.0 and the change in scope referenced here.
I like to add more markup to the templates like this for other devs to be able to quickly recognize whats going on in the javascript without having to open the Route's controller.
You could also replace "content" with "arrangedContent" if you decide to set some #sortProperties on the array controller.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With