【问题标题】:How to declare the item controller in an array controller - ember.js如何在数组控制器中声明项目控制器 - ember.js
【发布时间】:2014-07-24 23:13:44
【问题描述】:

我正在尝试编写 Todo 应用程序(使用 ember-cli)。当我在我的 todos 资源下添加活动和完整的路线时,我的项目控制器停止工作。在我在我的 Array 控制器中使用 itemController 来设置我的 Object 控制器之前。

路由器.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;

控制器/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;

控制器/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;

在我添加嵌套路由之前,todo.js 中的操作有效,现在当我尝试 todo.js 中的任何操作时,我会在控制台中看到以下内容:

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.

从 cmets 添加下面的模板....

模板/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>

模板/待办事项/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>

【问题讨论】:

  • 能否展示您的模板,很可能您没有使用itemController
  • 签入 Ember Chrome 调试器并查看视图层次结构。您将看到正在使用的控制器并找出它不工作的原因。我的猜测是它正在寻找 TodoIndexController,如果您在模板中使用这样的路由。另外,请记住,如果适合您的需要,您可以在 Routes 中添加操作。
  • 谢谢大家,添加了模板,确定这很简单,我没有以正确的 ember 方式进行操作。
  • 谢谢@steveH。我查看了视图层次结构。它是 application -> todos -> todos.index 我看到 todos.index 正在使用生成的 todos.index 控制器,所以我将我的控制器复制到 controllers/todos/index.js 并且它工作。现在只需要弄清楚如何让它与活动和完整的路由一起工作,当然不需要在 todos 文件夹中使用 3 个相同的控制器。

标签: ember.js


【解决方案1】:

将您的模板更改为:

{{#each todo in content itemController="todo"}}
    {{#with todo}}
        ...
    {{/with}}
{{/each}}

由于 Ember 1.6.0 中的更新和引用 here 的范围更改,我添加了 {{with}} 块。

我喜欢像这样为模板添加更多标记,以便其他开发人员能够快速识别 javascript 中发生的事情,而无需打开 Route 的控制器。

如果您决定在数组控制器上设置一些#sortProperties,也可以将“content”替换为“arrangedContent”。

【讨论】:

  • 这让我的代码也能正常工作。很奇怪;我从未在指南中看到itemController 是必需的,甚至没有在模板中使用过。
  • 太棒了!感谢您提及#with
  • 这个问题有点晚了 - 但是在 EmberCLI 中同时拥有 ArrayController 和 ObjectController 而不必指定 ObjectController 的正确方法是什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-26
  • 1970-01-01
  • 1970-01-01
  • 2018-01-06
  • 2013-09-13
  • 1970-01-01
相关资源
最近更新 更多