简体   繁体   English

如何使用Knockout JS在列表中添加和删除项目?

[英]How do I add and remove items from a list using Knockout JS?

I'm trying to learn Knockout and I'm following these two tutorials: 我正在尝试学习淘汰赛,并且正在关注以下两个教程:
Tutorial 1 教程1
Better list example 更好的清单示例

But after half a day of trying (and failing), I'm not able to add or remove an item. 但是经过半天的尝试(失败),我无法添加或删除项目。
Here is my fiddle . 这是我的小提琴

Any help would be greatly appreciated! 任何帮助将不胜感激!

To clarify 澄清
Why doesn't self.items.push() add the new item to my list? 为什么self.items.push()将新项目添加到我的列表中? Is it because of the self.item_id property? 是因为self.item_id属性吗?

My HTML is like this: 我的HTML是这样的:

<input type="hidden" value="" data-bind="value: item_id" />
<input class="form-control" type="search" data-bind="value: item_name" />     
<button class="btn" data-bind="click: addItem, enable: item_name().length > 2">Add</button>

<ul data-bind="foreach: items">     
  // This list is retrieved from database on page load
  <li class="list-group-item">
    <span id="123" data-bind="text: item_name, attr: {'id': item_id}">Americanino</span>
    <span data-bind="click: $parent.removeItem"></span>
  </li>      

  <li class="list-group-item">
    <span id="842" data-bind="text: item_name, attr: {'id': item_id}">Diesel</span>
    <span data-bind="click: $parent.removeItem"></span>
  </li>          
</ul> 

And my JS looks like this: 我的JS看起来像这样:

function item(id, name){
    var self = this;
    self.item_id = ko.observable(id);
    self.item_name = ko.observable(name);    
    //test
    alert(self.item_id() + ' - ' + self.item_name());    
}

var manageListModel = function() {
    var self = this;
    self.items = ko.observableArray();
    self.item_id = ko.observable('345');
    self.item_name = ko.observable();

    self.addItem = function() {     
        if (self.item_name() != "") {      
            self.items.push(new item(self.item_id(),self.item_name()));
            self.item_name(""); 
        }
    }.bind(self); 

    // Remove item
    self.removeItem = function(item) {
        alert('tert');
        self.items.remove(item);
    }
};

ko.applyBindings(new manageListModel());

UPDATE UPDATE

So after banging my head in the wall for a few hours, I finally found a solution that works pretty well. 因此,在将我的头撞在墙上几个小时之后,我终于找到了一个效果很好的解决方案。 I hope this code will help other with similar problems :) 我希望这段代码可以帮助其他有类似问题的人:)

So what did I do? 那我该怎么办?

  • I created a template for the list item. 我为列表项创建了一个模板。 If you have 10 items in your list and use ko.observableArray() , the template will consists of 10 items. 如果列表中有10个项目并使用ko.observableArray() ,则模板将包含10个项目。 So for every item you add, you will get 10 in the list. 因此,对于您添加的每个项目,您将在列表中得到10。

  • I cloned the existing list since ko.observableArray() removes any static content in the list 我克隆了现有列表,因为ko.observableArray()删除了列表中的所有静态内容

  • Looped through my cloned list and put the value-data into an array which I passed into ko.observableArray 遍历我的克隆列表并将值数据放入一个数组中,该数组传递给ko.observableArray

Here is my final code: 这是我的最终代码:
( You can see the fiddle here ) 你可以在这里看到小提琴

My HTML: 我的HTML:

<input type="hidden" value="" data-bind="value: item_id" />
<input class="form-control" type="search" data-bind="value: item_name" />     
<button class="btn" data-bind="click: addItem, enable: function(){item_name().length > 2}">Add</button>

<ul data-bind="template: { name: 'item-item-template', data: $root.items}">     
  // This list is retrieved from database on page load
  <li class="list-group-item">
    <span id="123" data-bind="text: item_name, attr: {'id': item_id}">Americanino</span>
    <span data-bind="click: $parent.removeItem"></span>
  </li>      

  <li class="list-group-item">
    <span id="842" data-bind="text: item_name, attr: {'id': item_id}">Diesel</span>
    <span data-bind="click: $parent.removeItem"></span>
  </li>          
</ul> 

<script type="text/html" id="item-item-template">
<!--ko foreach: $data-->
    <li>
      <span id="" data-bind="text: item_name, attr: {'id': item_id}"></span>
      <a href="#" class="remove el-icon-remove-circle" data-bind="click: $root.removeitem"></a>
    </li>
<!-- /ko -->
</script>

The JS code JS代码

// List item
function brand(name, id) {
    var self = this;
    self.item_name = ko.observable(name);
    self.item_id = ko.observable(id);
}


// Create array of existing list
function create_list(exiting_list){
    var arr_list = [];

    $(exiting_list).find('li').each(function(e,li){
        var id = $(li).find('span').prop('id');
        var name = $(li).find('span').html();
        arr_list.push({
                 item_id: id,
                 item_name: name
             });
     });
    return arr_list;
}

// Manage list
// Fiddle: http://jsfiddle.net/spstieng/THJE3/46/
var manageitemListModel = function() {
    var self = this;

    // Data
    var exiting_list = $('.item-list ul').clone();
    self.items = ko.observableArray(create_list(exiting_list));
    self.item_name = ko.observable('');
    self.item_id = ko.observable('');

    // Operations
    self.additem = function() {
        if (self.item_name() != "") {
            self.items.push(new item(self.item_name(),self.item_id()));
            self.item_name("");
        }
    }.bind(self);

    // Remove item
    self.removeitem = function(item) {
        self.items.remove(item);
    }
};

ko.applyBindings(new manageitemListModel());

Take a look on the following version 看一下以下版本

Don't forget press F12 in your favorite browser, your binding was incorrect item_name().length > 2 不要忘了在您喜欢的浏览器中按F12键,您的绑定不正确item_name().length > 2

  • You can initialise self.item_name = ko.observable(""); 您可以初始化self.item_name = ko.observable("");
  • create additional computed property ( as for me this version is better ) 创建其他计算属性( 对我而言,此版本更好

For instance 例如

self.enableToAdd = ko.computed(function(){
    return self.item_name().length >2;
});

<button class="btn" data-bind="click: addItem, enable:enableToAdd">Add</button>

Here's more about Computed Observables 这是有关计算可观察物的更多信息

Please note: if a binding has any error, all the binding doesn't work 请注意:如果绑定有任何错误,则所有绑定均无效

Your "enable" function is requiring an object that is not defined by the time it's accessed. 您的“启用”功能需要一个在访问时尚未定义的对象。 You need to verify if it exists before using its value. 您需要先验证它是否存在,然后再使用其值。 Here's a working version of the HTML 这是HTML的有效版本

<div class="wrapper">

  <div class="input-group">
    <input type="hidden" value="" data-bind="value: item_id" />
    <input class="form-control" type="search" data-bind="value: item_name" />     

    <span class="input-group-btn">
      <button class="btn" data-bind="click: addItem, enable: item_name() ? item_name().length > 2 : false">Add</button>
    </span>
  </div>

  <ul class="list-group" data-bind="foreach: items">

    <li class="list-group-item">
      <span data-bind="text: item_name, attr: {'id': item_id}"></span>
      <span class="glyphicon glyphicon-remove-circle" data-bind="click: $parent.removeItem"></span>
    </li>      

  </ul>    

</div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM