0

I downloaded the code from Git and here is the link https://github.com/MikeWasson/LocalAccountsApp

In this visual studio solution we have JavaScript file called app.js which has the following code.

function ViewModel() {
var self = this;
var tokenKey = 'accessToken';

self.result = ko.observable();
self.user = ko.observable();

self.registerEmail = ko.observable();
self.registerPassword = ko.observable();
self.registerPassword2 = ko.observable();

self.loginEmail = ko.observable();
self.loginPassword = ko.observable();

function showError(jqXHR) {
    self.result(jqXHR.status + ': ' + jqXHR.statusText);
    //self.loginPassword();
}

self.callApi = function () {
    self.result('');

    var token = sessionStorage.getItem(tokenKey);
    var headers = {};
    if (token) {
        headers.Authorization = 'Bearer ' + token;
    }

    $.ajax({
        type: 'GET',
        url: '/api/values',
        headers: headers
    }).done(function (data) {
        self.result(data);
    }).fail(showError);
}

self.register = function () {
    self.result('');

    var data = {
        Email: self.registerEmail(),
        Password: self.registerPassword(),
        ConfirmPassword: self.registerPassword2()
    };

    $.ajax({
        type: 'POST',
        url: '/api/Account/Register',
        contentType: 'application/json; charset=utf-8',
        data: JSON.stringify(data)
    }).done(function (data) {
        self.result("Done!");
    }).fail(showError);
}

self.login = function () {
    self.result('');

    var loginData = {
        grant_type: 'password',
        username: self.loginEmail(),
        password: self.loginPassword()
    };

    $.ajax({
        type: 'POST',
        url: '/Token',
        data: loginData
    }).done(function (data) {
        self.user(data.userName);
        // Cache the access token in session storage.
        sessionStorage.setItem(tokenKey, data.access_token);
    }).fail(showError);
}

self.logout = function () {
    self.user('');
    sessionStorage.removeItem(tokenKey)
   }
  }
     var app = new ViewModel();
     ko.applyBindings(app);

What I'm not able to understand that how come properties like

self.result, self.registerEmail, self.registerPassword/Password2, self.loginEmail, self.loginPassword 

became methods. Because when I type "self" followed by a dot the intellisense gives all the above mentioned "self" properties as methods. Like

  self.result(), self.registerPassword()

And obviously "ko" comes from Knockout.js library.

But when I try to imitate the same in my simple JavaScript code. It fails and I know it's not right to do it here

  var SomeObj = {
  ok : function()
   {
    var x = 10, y= 10, z;
    z = x+ y;
    return z;
   }
 }


  function ViewModel()
  {
     var self = this;
     self.result = SomeObj.ok();
     function xyz()
     {
        self.result();
         alert(5700);
     }
}

var v = new ViewModel();
alert(v.result());  

But how come object "self" has declared "result" as property and used it later like a method in app.js where as when I try

     alert(v.result());

in the alert statement It gives me an exception but if I do

     alert(self.result()); 

in app.js it gives me back "undefined" but why not an exception the way I get in my code.

3
  • 1
    ko.observable is a method that returns yet another function. That's why self.result, etc. can be called likeself.result() - they're functions. Commented May 19, 2016 at 0:06
  • That's exactly the same thing I had in my mind was just not sure whether it's right or wrong. Commented May 19, 2016 at 0:09
  • If inside ok: function () {... you return another function that calculates and returns z I think you'd get what you're looking for. If that's a bit confusing (I might not have explained it that well) I can post an answer with what I mean. EDIT: I see @Neil Cross already posted what I was trying to explain. Commented May 19, 2016 at 0:14

1 Answer 1

2

The problem you're seeing here is that by using the parenthesis, you're invoking the SomeObj.ok method, rather than assigning it as a function. To store the method as a function pointer you should do the following:

self.result = SomeObj.ok;

Following this you'll be able to use self.result() to execute the assigned method which will return the result of the assigned SomeObj.ok method.

Check the definition of observable here: It defines a function which returns a function, which also provides logic for reads and writes based on whether a parameter is sent. If your ok function returned a function, rather than the result, you could access it the same way as observable.

var SomeObj = {
  ok : function() {
    return function() {
      var x = 10, y= 10, z;
      z = x+ y;
      return z;
    }
  }
}

Now, the assignment self.result = SomeObj.ok(); would prime self.result with a function, and as such calling self.result() will invoke the function assigned.

Sign up to request clarification or add additional context in comments.

5 Comments

I 100% agree with you. And what your are saying is dead right. But the thing is that's not how it's been written in app.js and that's the whole point of confusion for me. You can download the code from Git and take a look at app.js yourself.
And I also tried to change self.result = ok.observable; rather than ok.observable();. But doing so messes up the UI. Try yourself please.
check the definition of observable here: github.com/knockout/knockout/blob/…
That's exactly the same thing I had in my mind was just not sure whether it's right or wrong. But definitely rather than just guessing it I should have looked into the observable method.
Yeah open source is great. Sorry for the short reply, I accidentally submitted that response before deciding that a comment wasn't an appropriate place to add the extra detail I wanted to provide.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.