使用Ember的Array Controller获取对特定模型的引用

时间:2014-02-18 15:50:45

标签: ember.js

我是Ember的新手,我发现他们的一些概念有点不透明。我有一个管理公司库存的应用程序。有一个屏幕列出了他们的整个库存,并允许他们编辑每个库存项目。默认情况下,文本字段处于停用状态,我想要一个'编辑项目'将disabled / true设置为disabled / false的按钮。我创建了以下正确呈现的内容:

Inv.InventoryitemsRoute = Ember.Route.extend({
      model: function(params) {
            return Ember.$.getJSON("/arc/v1/api/inventory_items/" + params.location_id);
    }

<script type="text/x-handlebars" data-template-name="inventoryitems">
    {{#each}}
      <div class='row'>
          <p>{{input type="text" value=header disabled="true"}}</p>
          <p>{{input type="text" value=detail disabled="true"}}</p>
          <button {{action "editInventoryItem" data-id=id}}>edit item</button>
          <button {{action "saveInventoryItem" data-id=id}}>save item</button>
       </div>
    {{/each}}
</script>

所以这在UI中渲染很好,但我不知道如何访问特定模型以将文本输入从disabled / true更改为disabled / false。如果我只是像普通的jQuery那样做,我会添加特定模型的id值,并在文本输入中放置一个id,以便我可以设置文本字段。基于阅读文档,似乎我想要一个控制器 - 我想要一个ArrayController用于这个模型实例还是Ember可以自己解决这个问题?

我以为我想做类似以下的事情,但警告身份证给我undefined

Inv.InventoryitemsController=Ember.ArrayController.extend({
    isEditing: false,

    actions: {
        editInventoryItem: function(){
          var model = this.get('model');  
          /*
          ^^^^
          should this be a reference to that specific instance of a single model or the list of models provided by the InventoryitemsRoute
          */
          alert('you want to edit this:' + model.id);  // <-undefined
        }
    }
});

在Ember文档中,他们使用播放列表示例(此处为:http://emberjs.com/guides/controllers/representing-multiple-models-with-arraycontroller/),如下所示:

App.SongsRoute = Ember.Route.extend({
  setupController: function(controller, playlist) {
    controller.set('model', playlist.get('songs'));
  }
});

但是这个例子有点令人困惑(出于几个原因)但在这个特殊情况下 - 我如何将他们的播放列表概念映射到我试图编辑单个库存项目?

2 个答案:

答案 0 :(得分:2)

<script type="text/x-handlebars" data-template-name="inventoryitems">
    {{#each}}
      <div class='row'>
          <p>{{input type="text" value=header disabled="true"}}</p>
          <p>{{input type="text" value=detail disabled="true"}}</p>
          <button {{action "editInventoryItem" this}}>edit item</button>
          <button {{action "saveInventoryItem" this}}>save item</button>
       </div>
    {{/each}}
</script>

actions: {
    editInventoryItem: function(object){
      alert('you want to edit this:' + object.id);
    }
}

你需要什么。但让我更详细地解释一下:

首先,术语:您的“模型”是绑定到控制器的整个对象。当您对阵列控制器中的操作调用this.get('model')时,您将收到整个模型,在这种情况下是一系列库存项目。

{{#each}}把手标签迭代选定的数组(默认情况下,它将整个模型用作所选数组)。在{{#each}}块帮助器中,您可以通过说this来引用当前所在的特定对象。您也可以通过键入this来命名迭代对象,而不是依赖于{{#each thing in model}}声明,其中每个对象都将被引用为thing

最后,您的行为能够接受输入。您只需在操作名称后面提供变量名称即可声明这些输入。上面,我使用{{action "saveInventoryItem" this}}演示了这一点,它会将this传递给动作saveInventoryItem。您还需要为该操作添加输入参数,以便接受它。

答案 1 :(得分:1)

好的,那是因为正如你所说,你刚刚开始使用Ember。我可能会这样做:

<script type="text/x-handlebars" data-template-name="inventoryitems">
  {{#each}}
    <div class='row'>
      <p>{{input type="text" value=header disabled=headerEnabled}}</p>
      <p>{{input type="text" value=detail disabled=detailEnabled}}</p>
      <button {{action "editInventoryItem"}}>edit item</button>
      <button {{action "saveInventoryItem"}}>save item</button>
    </div>
  {{/each}}
</script>

有了这个,你需要在InventoryitemController中定义一个headerEnabled属性(注意它是单数的,而不是包含所有项的那个),而对于detailEnabled和动作,你也可以在相同的控制器或路线:

App.InventoryitemController = Ember.ObjectController.extend({
  headerEnabled: false,
  detailEnabled: false,

  actions: {
    editInventoryItem: function() {
      this.set('headerEnabled', true);
      this.set('detailEnabled', true);
    }
  }
});

这只是一个如何访问数据的示例,如果相同的属性将启用两个文本字段,那么您只需要一个,而不是我放的两个。如果'each'循环没有选择正确的控制器,只需指定itemController。