名为w / o params的createRecord不会将对象添加到集合中

时间:2013-01-26 19:31:43

标签: ember.js ember-data

使用:

  • 余烬-1.0.0-pre.4.js
  • ember-data.js修订:11
  • 车把-1.0.rc.2.js

请查看说明所述问题的jsFiddle

我有一个模板中显示的项目列表。该模板包含一个linkTo帮助程序,让控制器将一个项目添加到集合中,并在页面上显示为文本输入。

将项目添加到集合中由控制器完成:

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();
    }
});

如果我希望显示新项目是列表,我必须将参数传递给createRecord,否则该项目不可见。使用Chrome的检查器可以重现相同的行为,然后可以按如下方式显示该项目:

// 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.

这是预期的行为,如果是,我在这里缺少什么?

2 个答案:

答案 0 :(得分:2)

我花了一些时间来重做你的例子,我认为应该用Emberjs正确完成事情。您应该确保交易并正确定义您的观点,然后解决您的所有问题。所以这就是我认为你应该这样做的方式

  • 定义文本字段的视图以捕获输入的值或 只需将其绑定到model属性即可。

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

<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>
  • 定义列出项目的不同状态并添加新项目

  • 受益于将文本字段值自动绑定到 如果是模型属性,则需要将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')
    }
});

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

答案 1 :(得分:0)

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

你的例子激励我重写我的代码。我也对你的方法做了一些改变:

  • 我不确定这是否是最佳做法,我不会创建store实例。相反,我定义了一个Store类。
  • 通过调用相应路径上的model属性来设置 TodoItemsNewController 的内容。
  • TodoItemsNewRoute中的renderTemplate只需要出口密钥。

    <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

欢迎任何评论。