Florin Florin - 4 months ago 9
Javascript Question

Knockout.JS: 'delete' request

Why doesn't it work to delete the element from the table and refresh the page ?
I got a web api with a delete method implemented that works just fine on Postman.
I have no idea what am I doing wrong. I've implemented the get using jquery and knockout.

<table data-bind="foreach: students">
<tr>
<th>ID</th>
<th>Nume</th>
<th>Prenume</th>
<th>Data</th>
</tr>
<tr>
<td><input type="text" id="id_" size="1" data-bind="value: StudId" disabled="disabled"></td>
<td><input type="text" size="60" data-bind="value: Nume" disabled="disabled"></td>
<td><input type="text" size="60" data-bind="value: Prenume" disabled="disabled"></td>
<td>
<input type="text" size="15" data-bind="value: Data" disabled="disabled">
<input type="button" value="Sterge" class="button button1" id="sterge" />
<input type="button" class="button button2" value="Editeaza" />
</td>
</tr>
</table>
<br /><br />
</div>


var uri = 'api/student'

function studentModel() {
var self = this;
self.students = ko.observableArray([]);

$.getJSON(uri, function (data) {
self.students(data);
})
}
ko.applyBindings(new studentModel());

$(function () {
$('#sterge').click(function () {
var id = $('#id_').val();
$.ajax({
type: 'DELETE',
url: uri + '/' + id,
success: function (result) {
alert('Student sters cu succes! ');
location.reload();
},
error: function (error) {
alert('Stergere esuata! ');
}
});
});
});

Answer

There are two things going wrong here:

  1. At the time you're attaching event listeners, the elements they need to be attached to do not yet exist.
  2. You're using id attributes inside a foreach binding: this will result in duplicate ids.

When knockout applies its bindings, the students observable array is still empty. Its items are loaded via the API.

I'd suggest using the click binding to attach your delete method. You should also remove the id attributes.

var testData = [
  { StudId: 1, Nume: "Jane", Prenume: "Deer", Data: 14 },
  { StudId: 2, Nume: "John", Prenume: "Doe", Data: 10 }
];



var uri = 'api/student';

var StudentsViewModel = function() {
  this.students = ko.observableArray();

  this.loadStudents();
};

StudentsViewModel.prototype.loadStudents = function() {
  var self = this;
  $.getJSON(uri, function(data) {
    self.students(data);
  });
};

StudentsViewModel.prototype.deleteStudent = function(id) {
  console.log("Post delete for id: " + id);
  $.ajax({
    type: 'DELETE',
    url: uri + '/' + id,
    success: function(result) {
      alert('Student sters cu succes! ');
    },
    error: function(error) {
      alert('Stergere esuata! ');
    }
  });
  
  
};

// Mock jquery ajax stuff
var $ = {
  getJSON: function(uri, cb) {
    setTimeout(cb.bind(null, testData), 750);
  },
  ajax: function() {}
};

// Apply bindings
ko.applyBindings(new StudentsViewModel());
input { width: 50px }
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<table >
  <tr>
    <th>ID</th>
    <th>Nume</th>
    <th>Prenume</th>
    <th>Data</th>
  </tr>
  <!-- ko foreach: students -->
  <tr>
    <td>
      <input data-bind="value: StudId" type="text" size="1" disabled="disabled">
    </td>
    <td>
      <input data-bind="value: Nume" type="text" size="60" disabled="disabled">
    </td>
    <td>
      <input data-bind="value: Prenume" type="text" size="60" disabled="disabled">
    </td>
    <td>
      <input data-bind="click: $parent.deleteStudent.bind($parent, $data.StudId)" type="button" value="Sterge" class="button button1"/>
    </td>
  </tr>
  <!-- /ko -->
</table>
<br />
<br />
</div>