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

2

9

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?

Lecroy answered 28/2, 2013 at 15:52 Comment(0)
A
4

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);
Atchley answered 28/2, 2013 at 15:55 Comment(2)
Thank you, this is helpful. But I only see from this how to make a computed observable from one property of the data (i.e. children -> nameLength). How it would be possible to make a computed observable from two or more properties?Lecroy
Sorry, I was out last night, so didn't see your follow-up question until now. Glad you got it sorted in the end. Technically, though, I'd say that I answered the question that you asked completely, so I'd have thought that an upvote was the least it deserved!Atchley
L
12

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);
Lecroy answered 28/2, 2013 at 20:31 Comment(0)
A
4

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);
Atchley answered 28/2, 2013 at 15:55 Comment(2)
Thank you, this is helpful. But I only see from this how to make a computed observable from one property of the data (i.e. children -> nameLength). How it would be possible to make a computed observable from two or more properties?Lecroy
Sorry, I was out last night, so didn't see your follow-up question until now. Glad you got it sorted in the end. Technically, though, I'd say that I answered the question that you asked completely, so I'd have thought that an upvote was the least it deserved!Atchley

© 2022 - 2024 — McMap. All rights reserved.