Difference Between Knockout View Models Declared as Object Literals VS Functions

Difference between knockout View Models declared as object literals vs functions

There are a couple of advantages to using a function to define your view model.

The main advantage is that you have immediate access to a value of this that equals the instance being created. This means that you can do:

var ViewModel = function(first, last) {
this.first = ko.observable(first);
this.last = ko.observable(last);
this.full = ko.computed(function() {
return this.first() + " " + this.last();
}, this);
};

So, your computed observable can be bound to the appropriate value of this, even if called from a different scope.

With an object literal, you would have to do:

var viewModel = {
first: ko.observable("Bob"),
last: ko.observable("Smith"),
};

viewModel.full = ko.computed(function() {
return this.first() + " " + this.last();
}, viewModel);

In that case, you could use viewModel directly in the computed observable, but it does get evaluated immediate (by default) so you could not define it within the object literal, as viewModel is not defined until after the object literal closed. Many people don't like that the creation of your view model is not encapsulated into one call.

Another pattern that you can use to ensure that this is always appropriate is to set a variable in the function equal to the appropriate value of this and use it instead. This would be like:

var ViewModel = function() {
var self = this;
this.items = ko.observableArray();
this.removeItem = function(item) {
self.items.remove(item);
}
};

Now, if you are in the scope of an individual item and call $root.removeItem, the value of this will actually be the data being bound at that level (which would be the item). By using self in this case, you can ensure that it is being removed from the overall view model.

Another option is using bind, which is supported by modern browsers and added by KO, if it is not supported. In that case, it would look like:

var ViewModel = function() {
this.items = ko.observableArray();
this.removeItem = function(item) {
this.items.remove(item);
}.bind(this);
};

There is much more that could be said on this topic and many patterns that you could explore (like module pattern and revealing module pattern), but basically using a function gives you more flexibility and control over how the object gets created and the ability to reference variables that are private to the instance.

Benefit of declaring knockout view model using IIFE

It's a matter of choosing the right tool for the job. Some viewmodels may be very simple, and so can be defined as inline objects. I often find that it helps to have the ability to define helper functions and private variables, in which case I will use the immediately-executing function form that you are asking about.

It is pretty rare that I need to create multiple instances of a viewmodel. If I did, I would use a named function that returns a viewmodel object.

As rare as it is to make multiple viewmodels of the same form, it is rarer still to need to inherit from them, or to need so many instances that sharing methods via prototype is a significant help. These are the only circumstances that warrant using actual constructors.

Knockout: how can I pass a model to a javascript object literal?

The code in your question you are mixing object literal syntax w/ variable assignment syntax. Also, in the function you should be assigning this to a self/that variable to alleviate scope issues. It also makes using ko.computed() a lot nicer.

var profileMod = function() { 
var self = this;
self.first = ko.observable("Bob");
self.last = ko.observable("Smith");
}

I've updated your fiddle http://jsfiddle.net/nn0mfe48/3/

Is viewModel a function or a object variable?

This answer explains the difference betweeen using an object literal and a function for defining a view model: Difference between knockout View Models declared as object literals vs functions

Knockout.js: what is the difference between ko.mapping and ko.observable ?

In some projects, sometimes the data object you get back from the server is complex, with lots of properties, which in turn have more properties. You may wish to make all, or a significant number of them observable, so that the UI is reactive to changes. It's a tedious job to manually create all those observables and assign the values.

The mapping plugin allows you to automatically generate observables for the properties of the data object. There are various customisations that you can do with the plugin, such as ignoring certain properties, or choosing which properties not to become observable vs just normal properties.

The main point here is that the underlying behaviour is exactly the same. It's all observables, just created in a different way. See Mapping for the Knockout documentation with examples.

Personally, I've not used the mapping plugin before. I've never really found a need for it. The application I work on is
componentized, which means for any given component, there isn't going to be a huge amount of data returned from the server/data source. Secondly, of that data that is used, only a handful of properties need to be made observable.

Difference between knockout and .NET View Models?

In convention you can use Knockout view-model is as client-side and MVC view-model is as server-side.

Your question : How do you decide which to use ?

Answer : You can use both as parallel.That means for your single cshtml page can have a knockout view-model is as below.It contains both properties and functions as a unit.This view-model for the behavior what you need for the client side functionality.

    //This is a simple Viewmodel
//JavaScript that defines the data and behavior of your UI
function AppViewModel() {
var self = this;
self.firstName = ko.observable();
self.lastName = ko.observable();

self.fullName = ko.computed(function () {
return self.firstName() + " " + self.lastName();
});

self.capitalizeLastName = function () {
var currentVal = self.lastName();//Read the current value
self.lastName(currentVal.toUpperCase());//Write back a modified value
};
}

But for show server side behaviors you can use more complex (or more properties) with the MVC view-model.That is for bring data from database and show those data in your view.

Conclusion: So you can use both view-models simultaneously when working with MVC.

Important Note : But if you need to use single view-model for both scenarios then you can do that thing also.For that you have to use KnockoutJS Mapping plugin.

It can be used like below.

<script src="~/Scripts/knockout.mapping-latest.js"></script>
<script type="text/javascript">
$(function() {
var viewModel = ko.mapping.fromJS(@Html.Raw(Model.ToJson()));
ko.applyBindings(viewModel);
});
</script>

You can get more details about this from Loading KnockoutJS View Models from ASP.Net MVC, for faster page loads

If you need to know more about Knockout check learn.knockoutjs

I hope this will help to you.

View-Model declaring of Knockout.js. There are two methods

The first way defines an object constructor but does not instantiate a new object, you can pass in arguments this way. If you're creating multiple objects/models this would definitely be less clunky than the second way.

The second way is using object initializer syntax, this instantiates a new object in memory with whatever fields you set it to. In general this produces for smaller code size; if you're creating two objects of the same or similar structures, use the first way.

There is no reason why you can't use the first in place of the second. Simply creating a new object and pass it in wherever it is needed.

This:

function AppViewModel(fName, lName) {
var self = this;
self.firstName = ko.observable(fName);
self.lastName = ko.observable(lName);
}
...
var appViewModel = new AppViewModel("Bert", "Bertington");

creates the same object as this:

var appViewModel = {
this.firstName = ko.observable("Bert"),
this.lastName = ko.observable("Bertington")
};

The first one just allows for more AppViewModels to be created, e.g. new AppViewModel("Joe", "Shmoe")



Related Topics



Leave a reply



Submit