billy jean
billy jean

Reputation: 1419

Why in knockout.js examples is the viewmodel sometime defined as a function and other times a direct variable definition?

i am trying to understand what is the best practice for defining and organizing my js viewmodels with knockout. I am not js genius so...

Ok so in many of the examples the viewModel is defined as:

var viewModel = {
    firstName: ko.observable("Bert"),
    lastName: ko.observable("Bertington"),

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

the other way is to create a sort of constructor:

 function viewModel() {
     this.firstName = ko.observable("Bert");
     this.lastName = ko.observable("Bertington"); etc.............

My instinct was to create my viewModels as function/classes but found that when defining functions inside for things like ajax calls etc, i was not able to update the viewModel variables inside the function definitions. I have to first define the viewModel and then "add" the functions after?

function LogOnModel() {
    this.userName = ko.observable("");
    this.password = ko.observable("");
    this.userNameExists = ko.observable(true);
    this.passwordCorrect = ko.observable(true);
    this.returnURL = ko.observable(document.location.href.replace("http://" + location.host,""));
    this.login = function () {
        $.ajax({
            type: 'POST',
            contentType: 'application/json; charset=utf-8',
            data: ko.toJSON(this),
            dataType: 'json',
            url: 'Account/LogOn',
            success: function (result) {
                this.userNameExists(result["UserNameExists"]);
                this.passwordCorrect(result["PasswordCorrect"]);
                alert(userLogOnModel.userNameExists);
            }
        });
    this.loginFormFilled = ko.dependentObservable(function () {
        if ((this.userName() != "") && (this.password() != ""))
            return true;
        else
            return false;
    }, this);

 }  

In the above the login function cannot update the userNameExists or passwordCorrect variables.. I tried a bunch of different syntax. When i move this function out of the constructor it works fine..

I just don't understand what would be the purpose of creating the sort of function constructor if none of the member function can exist inside it? What am i missing? thanks!

Upvotes: 9

Views: 3821

Answers (1)

RP Niemeyer
RP Niemeyer

Reputation: 114792

Your issue is likely the value of this in your callback. There are a couple of ways to make this work:

$.ajax accepts a context parameter, so you could do add context: this into your options that are passed to it.

You could also set this to a variable inside of this.login and use the variable in your result. It would be like:

this.login = function() {
    var that = this;
    ....
    success: function (result) {
                that.userNameExists(result["UserNameExists"]);
                that.passwordCorrect(result["PasswordCorrect"]);
            }
}

Or you could bind your success function to this, which will ensure that the function is called with the correct value for this. It wpuld be like

success: function (result) {
                this.userNameExists(result["UserNameExists"]);
                this.passwordCorrect(result["PasswordCorrect"]);
                alert(userLogOnModel.userNameExists);
            }.bind(this)

Since, you are using $.ajax, the first option is the easiest.

Upvotes: 8

Related Questions