2

Using:

  • ember-1.0.0-pre.4.js
  • ember-data.js REVISION:11
  • handlebars-1.0.rc.2.js

Please have a look at this jsFiddle illustrating the described problem.

I have a list of items that are displayed in a template. The template contain a linkTo helper that let's the controller add an item to the collection and is shown as a text input on the page.

Adding the item to the collection is done by the controller:

App.TodoItem = DS.Model.extend({
    title: DS.attr('string', { defaultValue: "unknown" })
});

App.Router.map(function () {
    this.resource('todo_items')
});

App.TodoItemsRoute = Em.Route.extend({
    model: function () {
        return App.TodoItem.find();
    }
});

App.TodoItemsController = Em.ArrayController.extend({
    addTodoItem: function () {
        App.TodoItem.createRecord();
    }
});

If I want the new item to be shown is the list, I have to pass params to createRecord, otherwise the item is not visible. The same behaviour can be reproduced by using Chrome's inspector and then the item can be made visible as follows:

// Open the jsFiddle http://jsfiddle.net/bazzel/BkFYd/ and select 'result(fiddle.jshell.net) in the inspector, then:
var item = App.TodoItem.createRecord();
// Nothing visible yet.

item.set('title', 'Whatever');
// Now the text input appear with the title as its value.

Is this expected behaviour and if so, what am I missing here?

4

2 回答 2

2

我花时间重做你的例子,我觉得应该用 Emberjs 正确地完成事情。您应该确保交易并正确定义您的观点,然后您的所有问题都会得到处理。所以我认为你应该这样做

  • 为文本字段定义一个视图以捕获输入的值或将其绑定到模型属性。

  • 列出项目和向列表添加新项目应在两个不同的视图中完成,不应混合在一起

<script type="text/x-handlebars">
    {{outlet}}
    <div>
        {{outlet 'addItem'}}
    </div>
</script>

<script type="text/x-handlebars" data-template-name="todo_items">
    {{#linkTo 'todo_items.new'}}Add Todo Item{{/linkTo}}
  <ul>
    {{#each item in controller}}
        <li>
            {{#unless item.isNew}}
              {{item.title}}
            {{/unless}}
        </li>
    {{/each}}
    </ul>
</script>
  • 为列出项目和添加新项目定义不同的状态

  • 要从将文本字段值自动绑定到模型属性中受益,您需要将 an 关联ObjectControllerTodoItemsNew路由

  • 最后,利用事务创建并提交记录到存储
window.App = Em.Application.create();

App.TodoItem = DS.Model.extend({
    title: DS.attr('string')
});

App.TodoItem.FIXTURES = [{
    id: 1,
    title: 'Lorem'
}, {
    id: 2,
    title: 'Ipsum'
}];

App.store = DS.Store.create({
    revision: 11,
    adapter: DS.FixtureAdapter.create()
});

App.Router.map(function () {
    this.resource('todo_items',function(){
      this.route('new');
    })
});

App.IndexRoute = Em.Route.extend({
    redirect: function () {
        this.transitionTo('todo_items');
    }
});

App.TodoItemsRoute = Em.Route.extend({
    model: function () {
        return App.TodoItem.find();
    }
});

App.TodoItemsNewRoute = Em.Route.extend({
    transaction: App.store.transaction(),

    setupController:function(controller) {
        console.info(controller.toString());
        controller.set('content',this.transaction.createRecord(App.TodoItem));
    },

    renderTemplate: function() {
        this.render('addItem',{
            into:'application',
            outlet:'addItem',
        })
    },
    events: {
      addItem: function() {
          this.transaction.commit();
            this.transitionTo('todo_items');
      }
    }
});


App.TodoItemsController = Em.ArrayController.extend();
App.TodoItemsNewController = Em.ObjectController.extend();
App.TextField = Ember.TextField.extend({
    insertNewline: function () {
      this.get('controller').send('addItem')
    }
});

这里' 是 jsfiddle 上示例的工作版本。希望我帮助这个例子澄清了你的一些问题。

于 2013-01-27T06:31:04.783 回答
0

谢谢肯回答我的问题。在 Ember 中这样做确实感觉像是一种更合适的方式。但是,我仍然认为很难掌握从哪里可以访问哪些对象......

你的例子启发了我重写我的代码。我还对您的方法进行了一些更改:

  • 我不确定这是否是最佳实践,我没有创建store实例。相反,我定义了一个Store类。
  • TodoItemsNewController的内容是通过调用相应路由上的模型属性来设置的。
  • TodoItemsNewRoute 中的 renderTemplate 只需要 outlet 键。

    <script type="text/x-handlebars">
        {{outlet}}
    </script>
    
    <script type="text/x-handlebars" data-template-name="todo_items">
        {{#linkTo 'todo_items.new'}}Add Todo Item{{/linkTo}}
        <ul>
        {{outlet "addItem"}}
        {{#each controller}}
            <li>
            {{#unless isNew}}
                {{title}}
            {{/unless}}
            </li>
        {{/each}}
        </ul>
    </script>
    
    <script type="text/x-handlebars" data-template-name="todo_items/new">
        {{view Ember.TextField valueBinding="title" placeholder="Enter title"}}
    

    window.App = Em.Application.create();
    
    App.TodoItem = DS.Model.extend({
        title: DS.attr('string', {
            defaultValue: "unknown"
        })
    });
    
    App.TodoItem.FIXTURES = [{
        id: 1,
        title: 'Lorem'
    }, {
        id: 2,
        title: 'Ipsum'
    }];
    
    App.Store = DS.Store.extend({
        revision: 11,
        adapter: DS.FixtureAdapter.create()
    });
    
    App.Router.map(function() {
        this.resource('todo_items', function() {
            this.route('new');
        });
    });
    
    App.IndexRoute = Em.Route.extend({
        redirect: function() {
            this.transitionTo('todo_items');
        }
    });
    
    App.TodoItemsRoute = Em.Route.extend({
        model: function() {
            return App.TodoItem.find();
        }
    });
    
    App.TodoItemsNewRoute = Em.Route.extend({
        model: function() {
            return App.TodoItem.createRecord();
        },
        renderTemplate: function() {
            this.render({
                outlet: 'addItem'
            });
        }
    });
    
    App.TodoItemsNewView = Em.View.extend({
        tagName: 'li'
    });
    

更新的示例在jsFiddle上。

欢迎任何评论。

于 2013-01-27T10:42:22.513 回答