如何在1.0版之前创建和扩展Ember.ArrayController

时间:2012-09-01 16:15:18

标签: ember.js

我有一个简单的ember.js你好世界只有一条路线

(function() {

  window.PersonApp = Ember.Application.create({

    ApplicationController: Ember.ObjectController.extend({}),

    ApplicationView: Ember.View.extend({
      templateName: 'application'
    }),

    Person: Ember.Object.extend({
      username: null,
      isActive: false
    }),

    PersonController: Ember.ArrayController.extend({
      content: [],

      addPerson: function(username) {
        var person = PersonApp.Person.create({ username: username });
        this.pushObject(person);
      },

      removePerson: function(person) {
        this.removeObject(person);
      }
    }),

    AddPersonTextField: Ember.TextField.extend({
      insertNewline: function() {
        var value = this.get('value');

        if (value) {
          PersonApp.PersonController.addPerson(value);
          this.set('value', '');
        }
      }
    }),

    RemovePersonCheckbox: Ember.Checkbox.extend({
      content: null,
      change: function(event) {
        PersonApp.PersonController.removePerson(this.content);
      },
    }),

    HomeController: Ember.Controller.extend(),
    HomeView: Ember.View.extend({
      templateName: 'home'
    }),

    Router: Ember.Router.create({
      root : Ember.Route.extend({
        index: Em.Route.extend({
          route: '/',
          connectOutlets: function(router){
            router.get('applicationController').connectOutlet('home');
          }
        })
      })
    })

  });

  $(function() {
    PersonApp.initialize(PersonApp.Router);
  });

})();

我的html模板非常基本,只是定义一个插座和1个“主页”视图,以用户名显示用户

<!DOCTYPE html>
<html>
<title>Users</title>
<link href="{{ STATIC_URL }}css/default.css" rel="stylesheet" type="text/css">
<script src="{{ STATIC_URL }}script/vendor/jquery-1.7.2.js" type="text/javascript"></script>
<script src="{{ STATIC_URL }}script/vendor/handlebars-1.0.0.beta.6.js" type="text/javascript"></script>
<body>
{% load templatetag_handlebars %}

<script type="text/x-handlebars" data-template-name="application">
  <div class="container">
  {% verbatim %}
    {{outlet}}
  {% endverbatim %}
  </div>
</script>

<script type="text/x-handlebars" data-template-name="home">
  {% verbatim %}
  {{view PersonApp.AddPersonTextField placeholder="username"}}
    <ul>
      {{#each PersonApp.PersonController}}
        <li>
          <label>
            {{view PersonApp.RemovePersonCheckbox contentBinding="this" checkedBinding="isActive"}}
            {{username}}
          </label>
        </li>
      {{/each}}
    </ul>
{% endverbatim %}
</script>

<script type="text/javascript" >
ENV = {
  CP_DEFAULT_CACHEABLE: true,
  VIEW_PRESERVES_CONTEXT: true
};
</script>

<script src="{{ STATIC_URL }}script/vendor/ember-1.0.pre.js" type="text/javascript"></script>
<script src="{{ STATIC_URL }}script/app/person.js" type="text/javascript"></script>
</body>
</html>

当这个运行时我得到错误

未捕获错误:断言失败:Ember.CollectionView的内容必须实现Ember.Array。您传递了PersonApp.PersonController

如果我尝试将Ember.ArrayController.extend切换为Ember.ArrayController.create我收到错误

未捕获的TypeError:对象没有方法'create'

环顾四周之后,似乎最新的ember可能会让我先调用ArrayController上的.create({})然后再调用.extend({})但是我找不到任何使用pre 1.0版本的好例子。有没有人知道上面我可能做错了什么?

1 个答案:

答案 0 :(得分:3)

这是一个有效的小提琴。 http://jsfiddle.net/feCYT/4/

在Ember pre中,使用路由器逻辑, extending ArrayController使PersonApp.PersonController

因此,PersonApp.PersonController是一般Class。您必须create此类的实例才能处理数据。

带有router的Ember为您执行此操作,作为路由器initializes,它会创建当时可用的控制器实例。因此,您已准备好一个实例,PersonApp.router.personController查看指示实例的人员的小型大写字母。

(值得看看DOM检查器上的“App.router”)

Functins之类的应该需要一些更改,请参阅注释行(这是一个快速修复):

    AddPersonTextField: Ember.TextField.extend({
        insertNewline: function () {
            var value = this.get('value');
            if (value) {
                PersonApp.router.personController.addPerson(value);//check this
                this.set('value', '');
            }
        }
    }),

这是一个快速修复,路由器的实际方式是,默认情况下,事件是路由器,我们将路由器委托给视图或控制器。深入挖掘路由器以找到它。

免责声明:我认为这是:)

评论bt @Luke Melia:

  

如您所述,您的事件处理程序示例并不理想。当。。。的时候   应用程序初始化,每个控制器实例都会有它   目标属性设置为路由器。当视图处理浏览器事件时   像insertNewLine一样,它应该将其转换为语义动作   发送到路由器。例如   this.get('controller.target')。send('addPerson',this.get('value'))。   然后当前路由可以处理要修改的“addPerson”操作   模型和控制器,它们将触发数据绑定   更新视图,一切都会很好,没有任何全局变量。