Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inserting a knockout computed observable in an observableArray that is generated with the ko.mapping plugin

Is it possible to manually insert a computed observable into an array that is generated with the mapping plugin? Here is an example that does not use the mapping plugin, but I would like to know if it could use it.

Lets say I have JSON data from the server:

[{
    "OrderID":1,
    "FirstName":"Bill",
    "LastName":"Smith",
},{
    "OrderID":2,
    "FirstName":"Jeff",
    "LastName":"Evans",
}
{
    "OrderID":3,
    "FirstName":"Dan",
    "LastName":"Johnson",
}]

On my view I have an Order class and a view model:

function Order(order) {
  var self = this;
  self.OrderID = ko.observable(order.OrderID);
  self.FirstName = ko.observable(order.FirstName);
  self.LastName = ko.observable(order.LastName);

  /*This is what I want to insert after the mapping plugin 
  generates "orders on the ViewModel*/
  self.FullName = ko.computed(function () {
      return self.FirstName() + ' ' + self.LastName();
  });

}

function ViewModel() {
  var self = this;
  self.orders = ko.observableArray([])

//Get orders
  $.ajax({
    url: '@Url.Action("orders")',
    type: "post",
    success: function (data) {
        var mappedOrders = $.map(data, function (item) { return new Order(item) });
        self.orders(mappedOrders);
     }
   })    
}

Is it possible to use the mapping plugin to generate the orders array on the view model, and also be able to insert the computed observable "FullName" in the orders array?

like image 816
Bradley Trager Avatar asked Feb 28 '13 15:02

Bradley Trager


2 Answers

After considering the documentation, I successfully applied it to my example as demonstrated in this jsFiddle and in the following lines:

var data = [{
    OrderID: '1',
    FirstName: 'Bob',
    LastName: 'Stevens'
}, {
    OrderID: '2',
    FirstName: 'Jim',
    LastName: 'Johnson'

}];

function order(data) {
    var self = this;
    var model = ko.mapping.fromJS(data, {}, self);
    model.FullName = ko.computed(function () {
        return self.FirstName() + ' ' + self.LastName();
    });
    return model;
}

var mapping = {
    create: function (options) {
        return new order(options.data);
    }
};

function viewModel() {
    var self = this;
    self.orders = ko.mapping.fromJS(data, mapping);
}

var vm = new viewModel();

ko.applyBindings(vm);
like image 98
Bradley Trager Avatar answered Oct 06 '22 23:10

Bradley Trager


You can, according to the documentation:

var mapping = {
    'children': {
        create: function(options) {
            return new myChildModel(options.data);
        }
    }
}

var myChildModel = function(data) {
    ko.mapping.fromJS(data, {}, this);

    this.nameLength = ko.computed(function() {
        return this.name().length;
    }, this);
}

var viewModel = ko.mapping.fromJS(data, mapping);
like image 44
Paul Manzotti Avatar answered Oct 07 '22 00:10

Paul Manzotti