I'm trying to learn Knockout and I'm following these two tutorials:
Tutorial 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? Is it because of the self.item_id
property?
My HTML is like this:
<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:
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
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. So for every item you add, you will get 10 in the list.
I cloned the existing list since ko.observableArray()
removes any static content in the list
Looped through my cloned list and put the value-data into an array which I passed into ko.observableArray
Here is my final code:
(You can see the fiddle here)
My 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
// 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());