如何将对象推送到observableArray [英] How to push object to an observableArray

查看:106
本文介绍了如何将对象推送到observableArray的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个模型,一个Foo有很多FooItem.如何将对象添加到FooItem?

I have this model, a Foo have many FooItem. How can I add an object to a FooItem?

我有这段代码,您可以建议甚至删除最适合这种情况的整个代码

I have this code, you can suggest or even erase the whole code that works best for this scenario

var Foo = function (selected) {
    this.id = ko.observable();
    this.name = ko.observable();
    this.fooItems = ko.observableArray([]);
    this.isSelected = ko.computed(function() {
        return selected() === this;
    }, this);
};

var FooItem = function () {
    this.id = ko.observable();
    this.selectedItemId = ko.observable();
    this.selectedName = ko.observable();
    this.remarks = ko.observable();
};

var foosFromDb = [{ id: 1, name: 'foo1' },
    { id: 2, name: 'foo2' },
    { id: 3, name: 'foo3' },
    { id: 4, name: 'foo4' }];

var fooItemsFromDb = [
    { id: 1, fooItem: 'fooItem1' },
    { id: 2, fooItem: 'fooItem2' },
    { id: 3, fooItem: 'fooItem3' },
    { id: 4, fooItem: 'fooItem4' },
    { id: 5, fooItem: 'fooItem5' },
    ];

var vm = (function () {
    var 
    	foos = ko.observableArray([]),
        fooItemsList = ko.observableArray([]),
    	loadFoos = function() {
            for(var i = 0; i < foosFromDb.length; i++) {
                foos.push(new Foo(selectedFoo)
                          .id(foosFromDb[i].id)
                          .name(foosFromDb[i].name));
            }
            
            selectFoo(foos()[0]);
        },
        loadFooItemsList = function() {
            for(var i = 0; i < fooItemsFromDb.length; i++) {
                fooItemsList.push({ id: fooItemsFromDb[i].id, name: fooItemsFromDb[i].fooItem });
            }
        },
        selectedFoo = ko.observable(),
        selectFoo = function(item) {
            selectedFoo(item);
        },
        newFoo =  function(item) {
           var id = foos().length + 1;
           var aFoo = new Foo(selectedFoo)
           				.id(id)
           				.name('');
            
            foos.push(aFoo);
            selectFoo(aFoo);
        },
        addFooItem = function(item){
            console.log(item); // In here I think I am getting the Selected Foo.
        };
    
    return {
        foos: foos,
        loadFoos: loadFoos,
        newFoo: newFoo,
        selectedFoo: selectedFoo,
        selectFoo: selectFoo,
        loadFooItemsList: loadFooItemsList,
        fooItemsList: fooItemsList,
        addFooItem: addFooItem
    };
}());

vm.loadFoos();
vm.loadFooItemsList();
ko.applyBindings(vm);

.container {
    float: left;
    width: 200px;
    height: 250px;
    border: 1px solid #ccc;
}
.selected  {
    background-color: red;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div class="container">
    <a href="#" data-bind="click: newFoo">New Foo</a>
    <table>
        <tr>
            <th>Foo Id</th>
            <th>Foo Name</th>
        </tr>
        <tbody data-bind="foreach: foos" style="cursor: pointer">
            <tr data-bind="click: $root.selectFoo, css: { selected: isSelected }">
                <td data-bind="text: id"></td>
                <td data-bind="text: name"></td>
            </tr>
        </tbody>
    </table>
</div>
<div data-bind="with: selectedFoo">
    <div class="container">
        <label>Id</label><br /><input type="text" data-bind="value: id" /><br />
        <label>Name</label><br /><input type="text" data-bind="value: name" /><br />
    </div>
    <div class="container">
        <label>Foo Item</label><br /><select data-bind="options: $root.fooItemsList, 
                                                        optionsText: 'name', 
                                                        optionsValue: 'id'"></select><br />
        <label>Remarks</label><br /><input type="text" /><br />
        <a href="#" data-bind="click: $root.addFooItem">Add Foo Item</a>
    </div>
        <div class="container">
        <table>
            <thead>
                <tr>
                    <th>FooItem</th>
                    <th>Remarks</th>
                </tr>
            </thead>
        </table>
    </div>
</div>
<div style="clear: both"></div>
<pre data-bind="text: ko.toJSON($root.selectedFoo, null, 2)"></pre>

当我click 添加Foo项时,我想填充字段中输入的表(最右边),并填充Foo.

When I click the Add Foo Item I would it like to be populate the table (in the farthest right) of what was entered in the fields and also populating the fooItems property of Foo.

我有这个小提琴供参考

欢迎您提出建议,技巧或任何编码实践.任何帮助将非常感激.谢谢

Suggestions, tips or any coding practice is welcome. Any help would be much appreciated. Thanks

编辑 我最终发布了整个视图模型.哪有错

EDIT I ended up posting the whole view model. Which is wrong

推荐答案

您缺少一些将所有内容连接起来所必需的东西.您的select未绑定任何内容,并且您也没有可观察到的绑定内容.我为此在Foo中添加了selectedItem成员.

You are missing a number of things that are necessary to hook everything up. Your select was not bound to anything, and you did not have an observable for it to bind to. I added a selectedItem member to Foo for this.

我将选择的optionsValue还原为正在选择的项目,因为我不想查找它.该值不是FooItem,而是具有id和name的简单对象.在addFooItem中,我根据对象数据创建一个新的FooItem并将其推送到fooItems列表中.

The optionsValue for the select I reverted to be the item being selected, because I don't want to look it up. The value isn't a FooItem, but is a simple object with id and name. In addFooItem, I create a new FooItem from the object data and push it onto the fooItems list.

表主体未定义,因此我将其设置为显示.由于某种原因,保存注释会使所有先前保存的注释更新.我不知道为什么会这样,但是我发现整个构造有些困难.

The table body wasn't defined, so I set that up to display. For some reason, saving a remark causes all the previously saved remarks to update. I don't know why that is, but I find the whole construction a bit hard to follow.

var Foo = function(selected) {
  this.id = ko.observable();
  this.name = ko.observable();
  this.fooItems = ko.observableArray([]);
  this.isSelected = ko.computed(function() {
    return selected() === this;
  }, this);
  this.selectedItem = ko.observable('quack');
};

var FooItem = function() {
  this.id = ko.observable();
  this.selectedItemId = ko.observable();
  this.selectedName = ko.observable();
  this.remarks = ko.observable();
};

var foosFromDb = [{
  id: 1,
  name: 'foo1'
}, {
  id: 2,
  name: 'foo2'
}, {
  id: 3,
  name: 'foo3'
}, {
  id: 4,
  name: 'foo4'
}];

var fooItemsFromDb = [{
  id: 1,
  fooItem: 'fooItem1'
}, {
  id: 2,
  fooItem: 'fooItem2'
}, {
  id: 3,
  fooItem: 'fooItem3'
}, {
  id: 4,
  fooItem: 'fooItem4'
}, {
  id: 5,
  fooItem: 'fooItem5'
}, ];

var vm = (function() {
  var
    foos = ko.observableArray([]),
    fooItemsList = ko.observableArray([]),
    loadFoos = function() {
      for (var i = 0; i < foosFromDb.length; i++) {
        foos.push(new Foo(selectedFoo)
          .id(foosFromDb[i].id)
          .name(foosFromDb[i].name));
      }

      selectFoo(foos()[0]);
    },
    loadFooItemsList = function() {
      for (var i = 0; i < fooItemsFromDb.length; i++) {
        fooItemsList.push({
          id: fooItemsFromDb[i].id,
          name: fooItemsFromDb[i].fooItem
        });
      }
    },
    selectedFoo = ko.observable(),
    selectFoo = function(item) {
      selectedFoo(item);
    },
    newFoo = function(item) {
      var id = foos().length + 1;
      var aFoo = new Foo(selectedFoo)
        .id(id)
        .name('');

      foos.push(aFoo);
      selectFoo(aFoo);
    },
    addFooItem = function(foo) {
      var itemData = foo.selectedItem(),
          item = new FooItem();
      item.id(itemData.id);
      item.selectedName(itemData.name);
      var r = vm.remark();
      console.debug("Remark:", r);
      item.remarks(r);
      foo.fooItems.push(item);
    };

  return {
    foos: foos,
    loadFoos: loadFoos,
    newFoo: newFoo,
    selectedFoo: selectedFoo,
    selectFoo: selectFoo,
    loadFooItemsList: loadFooItemsList,
    fooItemsList: fooItemsList,
    remark: ko.observable(),
    addFooItem: addFooItem
  };
}());

vm.loadFoos();
vm.loadFooItemsList();
ko.applyBindings(vm);

.container {
  float: left;
  width: 200px;
  height: 250px;
  border: 1px solid #ccc;
}
.selected {
  background-color: red;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div class="container">
  <a href="#" data-bind="click: newFoo">New Foo</a>
  <table>
    <tr>
      <th>Foo Id</th>
      <th>Foo Name</th>
    </tr>
    <tbody data-bind="foreach: foos" style="cursor: pointer">
      <tr data-bind="click: $root.selectFoo, css: { selected: isSelected }">
        <td data-bind="text: id"></td>
        <td data-bind="text: name"></td>
      </tr>
    </tbody>
  </table>
</div>
<div data-bind="with: selectedFoo">
  <div class="container">
    <label>Id</label>
    <br />
    <input type="text" data-bind="value: id" />
    <br />
    <label>Name</label>
    <br />
    <input type="text" data-bind="value: name" />
    <br />
  </div>
  <div class="container">
    <label>Foo Item</label>
    <br />
    <select data-bind="options: $root.fooItemsList, 
                       optionsText: 'name', 
                       value: selectedItem"></select>
    <br />
    <label>Remarks</label>
    <br />
    <input type="text" data-bind="value: $root.remark" />
    <br />
    <a href="#" data-bind="click: $root.addFooItem">Add Foo Item</a>
  </div>
  <div class="container">
    <table>
      <thead>
        <tr>
          <th>FooItem</th>
          <th>Remarks</th>
        </tr>
      </thead>
      <tbody data-bind="foreach: fooItems">
        <td data-bind="text:selectedName"></td>
        <td data-bind="text:$root.remark"></td>
        </tbody>
    </table>
  </div>
</div>
<div style="clear: both"></div>
<pre data-bind="text: ko.toJSON($root.selectedFoo, null, 2)"></pre>

这篇关于如何将对象推送到observableArray的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆