You should read up on the this
keyword.
First problem is with the self:this
thing inside the object literal.
Inside an object literal, this
will not refer to that object. In your code it will refer to the document
, because the nearest scope is the $(function() { ... });
setup, which is equivalent to (see docs) $(document).ready(...)
where this
is (somewhat more obviously) bound to document
.
Here's an example to demonstrate this, A, B, and C all log the same thing (which is not the viewModel
):
console.log(this.document); // A
$(function() {
var customers = [{
name: 'robert'
}];
console.log(this); // B
var viewModel = {
self: this
};
console.log(viewModel.self); // C
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Note also that this
inside your removeItem
function will refer to its closest function scope by default, which is the removeItem
function itself (and not window
, document
, or viewModel
).
Solution 1: if you really want to use object literals, you could first declare the object and add its properties later, e.g.:
var viewModel = {};
viewModel.list = ko.observableArray(customers);
viewModel.removeItem = function(place) {
viewModel.list.remove(place);
};
Solution 2: if you want to use the self = this
idiom I recommend using a constructor function instead:
function ViewModelConstructor(myCustomers) {
var self = this;
self.list = ko.observableArray(myCustomers);
self.removeItem = function(place) {
self.list.remove(place);
};
}
// Get an instance:
var viewModel = new ViewModelConstructor(customers);
To put that last suggestion into a fully runnable example:
var customers=[
{name:'robert'},
{name:'miguel'},
{name:'felipe'},
{name:'juan'}
];
function ViewModelConstructor(myCustomers) {
var self = this;
self.list = ko.observableArray(myCustomers);
self.removeItem = function(place) {
self.list.remove(place);
};
}
// Get an instance:
var viewModel = new ViewModelConstructor(customers);
ko.applyBindings(viewModel);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<table>
<tbody data-bind="foreach: list">
<tr>
<td data-bind="text: name"></td>
<td><a href="#">Edit</a></td>
<td><a href="#" data-bind="click: $root.removeItem">Delete</a></td>
</tr>
</tbody>
</table>