javascriptjqueryknockout.jsdata-bindingknockout-components

Knockout pushing observable and computed data to an observable array


I am trying to push multiple data (firstname and lastname), along with it when I compute the firstname and lastname and try to push the data in the same array I am thrown an error. Below is my code.

ViewModel:

var viewModel = function () {

  var self = this;

  self.gameofthrones = ko.observableArray ([
    {firstname: 'Jon', lastname: 'Snow'},
    {firstname: 'Robb', lastname: 'Stark'}
  ]);

  self.firstname = ko.observable('');
  self.lastname = ko.observable('');
  for (var i=0; i<self.gameofthrones().length; i++) {
    self.gameofthrones()[i].fullname = ko.computed (function () {
      return self.gameofthrones()[i].firstname+" "+self.gameofthrones()[i].lastname;
    })
  };

  $('#classic').click( function() {
    self.gameofthrones.push(
      {firstname: $('#fn').val(), lastname: $('#pr').val()}
    );
  });
}
ko.applyBindings(new viewModel());

HTML View:

<form class="" action="index.html" method="post">
  <input type="text" name="name" data-bind="value: firstname" id="fn">
  <input type="text" name="name" data-bind="value: lastname" id="pr">
  <button id="classic" type="button" name="Submit">Submit</button>
</form>

<div data-bind="foreach: gameofthrones">
  Firstname: <span data-bind="text: firstname"></span><br>
  LastName: <span data-bind="text: lastname"></span><br>
  Fullname: <span data-bind="text: fullname"></span><br><br>
</div>

I am new to Knockout JS and am stuck at this point is there a way to show the computed firstname and lastname in observable array. Thanks for you help in advance.


Solution

  • If you add a fullname computed function to each object of gameofthrone array, then you need to do the same when you push a new object to the array as by default it won't have one.

    There are many ways to accomplish this, but I think the simplest will be to create a function to get full name outside the observable array of gameofthrone. Then use $parent to call that function from inside foreach.

    var viewModel = function () {
      var self = this;
      self.gameofthrones = ko.observableArray ([
        {firstname: 'Jon', lastname: 'Snow'},
        {firstname: 'Robb', lastname: 'Stark'}
      ]);
      self.getFullName = function(name){
        return name.firstname + " " + name.lastname;
      }
    }
    ko.applyBindings(new viewModel());
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
    
    <div data-bind="foreach: gameofthrones">
      Firstname: <span data-bind="text: firstname"></span><br>
      LastName: <span data-bind="text: lastname"></span><br>
      Fullname: <span data-bind="text: $parent.getFullName($data) "></span><br><br>
    </div>