Access ViewModel in Knockout Mapping Plugin


SapuA

I'm using the knockout map plugin to add a computed property to an item in an observable array. However, this computed property depends on other properties in my view model.

How can I access viewmodel properties when creating an observable during mapping?

Note that I can't use options.parent because the property is further down in the viewModel.

I also can't change the viewmodel because it's generated on the server side.

edit:

Here's a JSFiddle showing the problem. The lines that are commented out are where I need to start working.

http://jsfiddle.net/g46mt/2/

This is what I have now, but obviously throws an error:

var mapping = {
    'Collection': {
        create: function(options) {
            var model = ko.mapping.fromJS(options.data);
            model.Total = ko.computed(function() {
                var result = this.Price() * viewModel.Count(); // :(
                return result;
            }, model);

            return model;
        }
    }
};

var json = { ... large json object ... };
var viewModel = ko.mapping.fromJS(json, mapping);
nemesv

A possible solution is to use this {deferEvaluation: true}option. So your computed function will only be evaluated when it is viewModelready and your Totalproperty has actually been used :

var mapping = {
    'Collection': {
        create: function(options) {
            var model = ko.mapping.fromJS(options.data);
            model.Total = ko.computed(function() {
                var result = this.Price() * viewModel.Count();
                return result;
            }, model, {deferEvaluation: true});
            return model;
        }
    }
};

Demo JSFiddle .

However, with this approach, you are tightly coupling the view model name with the mapping options. Because if you change var viewModel = ko.mapping.fromJS(json, mapping);and name it viewModeldifferently, you must also update the mapping configuration.

Since it may not be possible to move the "parent" chain in the mapping configuration in this case, the mapping plugin is not the best solution...

Here's an alternative to using a hand-written view model and passing the "root" where needed:

var MainViewModel = function (json) {    
    ko.mapping.fromJS(json, { 'ignore': ["Foo"] }, this); //map the rest
    this.Foo = new FooViewModel(json.Foo, this);
}

var FooViewModel = function (json, root) {
    ko.mapping.fromJS(json, { 'ignore': ["Bar"] }, this); //map the rest
    this.Bar = new BarViewModel(json.Bar, root);
}

var BarViewModel = function (json, root) {
    ko.mapping.fromJS(json, { 'ignore': ["Collection"] }, this); //map the rest
    this.Collection = ko.mapping.fromJS(json.Collection, {
       create: function(options) {
            var model = ko.mapping.fromJS(options.data);
            model.Total = ko.computed(function() {
                var result = this.Price() * root.Count();
                return result;
            }, model);

            return model;

       }});
}

Demo JSFiddle .

Related


Access ViewModel in Knockout Mapping Plugin

SapuA I'm using the knockout map plugin to add a computed property to an item in an observable array. However, this computed property depends on other properties in my view model. How can I access viewmodel properties when creating an observable during mapping

How to use the Knockout Mapping plugin in Hottowel

Gildas Tambo I was able to install ko.mapping in Visual Studio , but when I try to map some Json data in the view, it doesn't work. Can anyone tell me what am I doing wrong? this is my view model define(['plugins/router', 'knockout', 'services/logger', 'durand

Knockout Mapping Plugin and Data Binding for Simple JSON

bear I'm having some problems figuring out why this simple Knockout mapping isn't working. I'm not sure if the returned JSON is invalid, or if my mapping is wrong, or if it's just the binding. The data structure is a parent Conversation object with an array of

Knockout.js workflow with mapping plugin

name I'm not sure if I understand the workflow that Knockout.js follows internally. I have a ViewModel that is defined dynamically using the mapping plugin. Its shape is: { current: { foo: 'foo', bar: 'bar', id: 0 } , ids: [1,2,3,4,5] } Each idsvalue cor

Access Knockout ViewModel data in Sammy route

Brandon In my Knockout/Sammy SPA, I want to access ViewModel data in Sammy route, however, Sammy route is executed before my Knockout behavior . It works for the initial route because I set it self.selectedPage()equal to the first page, but not for subsequent

Access Knockout ViewModel data in Sammy route

Brandon In my Knockout/Sammy SPA, I want to access ViewModel data in Sammy route, however, Sammy route is executed before my Knockout behavior . It works for the initial route because I set it self.selectedPage()equal to the first page, but not for subsequent

Knockout table mapping plugin does not work with object arrays

Varunkumar Manohar Knockout maps cannot handle arrays of objects. Here is my fiddle http://jsfiddle.net/varunfiddle/03rv2the/ Basically, I'm trying to map an array of objects to an array of observables. var ViewModel = function() { var self = this; var

Correctly map array elements using Knockout mapping plugin

ØyvindBråthen I have a viewModel that looks like this after simplification: var viewModel = function(){ var self = this; self.selectedObject = ko.observable({}); self.getUnit = function(){ //get the selected object from the server side as json se

Knockout.mapping plugin only maps certain properties

intrinsic I would like to use knockout mapping to map only a given list of properties and no other properties (existing in the model). var propertiesToMap = ["PeriodStartDate", "PeriodEndDate", ...] knockout.mapping.fromJS(data, {}, myModel)All properties wil

Correctly map array elements using Knockout mapping plugin

ØyvindBråthen I have a viewModel that looks like this after simplification: var viewModel = function(){ var self = this; self.selectedObject = ko.observable({}); self.getUnit = function(){ //get the selected object from the server side as json se

Access Knockout component DOM from desired AMD viewModel

Silicon Valley I load my Knockout components this way: ko.components.register("example", { viewModel: {require: "widgets/example"}, template: {require: "text!widgets/example.html"} }); with example.js(extremely simplified): "use strict"; define(["kn

Access Knockout component DOM from desired AMD viewModel

Silicon Valley I load my Knockout components this way: ko.components.register("example", { viewModel: {require: "widgets/example"}, template: {require: "text!widgets/example.html"} }); with example.js(extremely simplified): "use strict"; define(["kn

Access Knockout component DOM from desired AMD viewModel

Silicon Valley I load my Knockout components this way: ko.components.register("example", { viewModel: {require: "widgets/example"}, template: {require: "text!widgets/example.html"} }); with example.js(extremely simplified): "use strict"; define(["kn

Update ViewModel in knockout

Sina Saydi I am new to knockout. I am trying to develop a shopping cart functionality using Knockout . My problem is when I want to put a counter in my cart , the counter will be applied to all cart contents. var FoodVM = function() { self.ID = ko.observable