2

Why I can't remove items from the array?

The html view, where I am trying to display all objects of the array:

<tbody data-bind="foreach:list" >
<tr> 
  <td data-bind="text:name" class="span10"></td> 
  <td><a class="icon-pencil" href="#"></a>Edit</td>
   here every time you click at the <a> tag i want to remove an element of the array. but it is not working
  <td><a class="icon-trash" href="#" data-bind="click:$root.removeItem " >
  </a>Delete</td>
</tr>
</tbody>

The script:

$(function () {
   var customers=[
      {name:'robert'},
      {name:'miguel'},
      {name:'felipe'},
      {name:'juan'},
      {name:'danilo'},
      {name:'federico'}
     ];

     var viewModel = {

        self:this,

        list: ko.observableArray(customers),

        // it's not removing the item of the array.
        removeItem: function(place) {
            this.list.remove(place);
        }
    };
    ko.applyBindings(viewModel);
});
Jeroen
  • 60,696
  • 40
  • 206
  • 339

2 Answers2

1

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>
Community
  • 1
  • 1
Jeroen
  • 60,696
  • 40
  • 206
  • 339
-1

Can you put like following

self:this,
self.list :  ko.observableArray(customers),

I think you have not put self

мalay мeнтa
  • 125
  • 3
  • 11