1
votes

I wanted to get values from form fields and save them as an object into an observableArray. And show them in the table. So, every time i hit 'add' button the table should be updated but its not working.

<select data-bind="options: gradeList, optionsText: 'Name', value: selectedGrade"></select>
<input type="text" data-bind="value: komark" />
<button data-bind="click: addMark">Add</button>
<table>
    <thead>
        <tr>
            <th>SN</th>
            <th>Name</th>
            <th>Mark</th>
        </tr>
    </thead>
    <tbody data-bind="foreach: allMarks">
        <tr>
            <td data-bind="$data.id"></td>
            <td data-bind="$data.name"></td>
            <td data-bind="$data.mark"></td>
        </tr>
    </tbody>
</table>
<p data-bind="text: allMarks"></p>

this is my html. 'gradeList' is also an observableArray but its working and i'm getting nice dropdown menu. On last 'p' element, text gets updated with every 'add' button click with [Object object] text but table never gets updated.

var newModel = function () {
    var self = this;
    self.komark = ko.observable();
    self.mark = ko.observable();
    self.selectedGrade = ko.observable();
    self.gradeList = ko.observableArray([]);
    self.allMarks = ko.observableArray([]);
    self.loadAllGrades = function () {
        $.ajax({
            type: "GET",
            dataType: "text",
            url: "studenthandler.ashx",
            data: { "action": "getAllGrades", "id": 0 },
            success: function (res) {
                self.gradeList(JSON.parse(res));
            },
            error: function () {
                alert("Failed to load.\nHit Refresh.");
            }
        });
    };

    self.addMark = function () {
        // console.log("button clicked");
        self.mark({ "id": self.selectedGrade().Id, "name": self.selectedGrade().Name, "mark": self.komark() });
        console.log(self.mark());
        self.allMarks.push(self.mark());
        console.log(self.allMarks());
    };
    self.loadAllGrades();
}

this is my javasript. The value of 'mark' and 'allMarks' gets updated in console but TABLE never gets updated.

1

1 Answers

1
votes

<td data-bind="$data.id"></td> doesn't do anything, you haven't specified a binding. You probably wanted:

<td data-bind="text: $data.id"></td>
<!-- ----------^^^^^^            -->

...and similar for name, mark.

Working example:

var newModel = function() {
  var self = this;
  self.komark = ko.observable();
  self.mark = ko.observable();
  self.selectedGrade = ko.observable();
  self.gradeList = ko.observableArray([]);
  self.allMarks = ko.observableArray([]);
  self.loadAllGrades = function() {
    /*
    $.ajax({
        type: "GET",
        dataType: "text",
        url: "studenthandler.ashx",
        data: { "action": "getAllGrades", "id": 0 },
        success: function (res) {
            self.gradeList(JSON.parse(res));
        },
        error: function () {
            alert("Failed to load.\nHit Refresh.");
        }
    });
    */
    self.gradeList.push(
      {Id: 1, Name: "Grade1"},
      {Id: 2, Name: "Grade2"},
      {Id: 3, Name: "Grade3"}
    );
  };

  self.addMark = function() {
    // console.log("button clicked");
    self.mark({
      "id": self.selectedGrade().Id,
      "name": self.selectedGrade().Name,
      "mark": self.komark()
    });
    //console.log(self.mark());
    self.allMarks.push(self.mark());
    //console.log(self.allMarks());
  };
  self.loadAllGrades();
}
ko.applyBindings(new newModel(), document.body);
<select data-bind="options: gradeList, optionsText: 'Name', value: selectedGrade"></select>
<input type="text" data-bind="value: komark" />
<button data-bind="click: addMark">Add</button>
<table>
    <thead>
        <tr>
            <th>SN</th>
            <th>Name</th>
            <th>Mark</th>
        </tr>
    </thead>
    <tbody data-bind="foreach: allMarks">
        <tr>
            <td data-bind="text: $data.id"></td>
            <td data-bind="text: $data.name"></td>
            <td data-bind="text: $data.mark"></td>
        </tr>
    </tbody>
</table>
<p data-bind="text: allMarks"></p>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

Side note: $data.id is a long way to write id. :-)


Side note 2: The [object Object] you're seeing for allMarks is because you're applying the text binding to an array of objects, so you get the default toString behavior of the object. You probably want a foreach for allMarks as well.