2

My Knockoutjs code goes as following:

function chainModel(){
        var self = this;
        this.total_count = ko.observable();

        function get_total_count(number){
            $.ajax({
                type : "get",
                url : "./XYZ/abc.php",
                cache : false,
                data : {number: number},
                success : function(result){
                    self.total_count($.parseJSON(result));
                },
                error : function(jqXHR, textStatus, errorThrown){
                    console.log("Error ! Unable to get step " + $number + " count." + "Error: " + errorThrown + ", Status: " + textStatus);
                }
            });
        }
    }

    ko.applyBindings(new chainModel());

Inside the get_total_count() function, I am assigning the ajax result to self.total_count observable. Instead, I would like to pass the observable too as an parameter to the get_total_count() function so that I can reuse the same function for more than one observable.

2
  • just out of curiosity: why are you using $ notation for the $number parameter? That is just a number? not a jQuery object Commented Nov 15, 2014 at 19:01
  • What prevents you from passing the observable as a parameter? Commented Nov 15, 2014 at 19:06

3 Answers 3

4

Here's a different approach which is using the the promise semantics of jQuery Ajax calls. Take a few minutes to familiarize yourself with jQuery Deferreds if the concept is new to you, it's worth it.

Quick note: By widely adopted convention, constructor names are PascalCase and all other names are camelCase in JavaScript. Don't use underscore_separated identifiers (nobody else does).

function ChainModel() {
    var self = this;

    self.totalCount = ko.observable();
    self.otherCount = ko.observable();

    function getCount(number) {
        return $.get("./XYZ/abc.php", {number: number})
        .fail(function (jqXHR, textStatus, errorThrown) {
            console.error(
                "Error ! Unable to get step " + number + " count." + 
                "Error: " + errorThrown + ", Status: " + textStatus
            );
        });
    }

    getCount(1).done(self.totalCount);
    getCount(2).done(self.otherCount);
}

ko.applyBindings(new ChainModel());

Since knockout observables are in fact functions and calling them sets their value, you can directly use them as success callbacks in Ajax calls.

By returning the jqXHR object from getCount(), you get access to the promise functions it exposes. So instead of passing in the target observable into getCount() you could pass it to the .done() callback, thus assigning the result of the Ajax call to it. Effectively this is separation of concerns and makes your code more flexible.

Other notes:

  • You should not have to force cache: false in an Ajax call. Set the appropriate Cache-Control header on the server side and the browser won't cache the call.
  • jQuery automatically parses the response for you, manually calling $.parseJSON() is not necessary.
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks. I still don't understand why '$.paseJSON()' is not necessary assuming that my PHP function returns an array indexed by column number. If I don't use '$.parseJSON()' then it displays data as [{"1234"}] .
When jQuery receives a JSON encoded response then it decodes it automatically. If your response data still is JSON after that, then it's very probably that it's double-encoded on the server - effectively a bug you need to fix on the server.
0

Isn't it as simple as passing the observable as an argument?

function chainModel(){
    var self = this;
    this.total_count = ko.observable();

    get_total_count(this.total_count, this.number);

    function get_total_count(observable, number){
        $.ajax({
            type : "get",
            url : "./XYZ/abc.php",
            cache : false,
            data : {number: number},
            success : function(result){
                observable($.parseJSON(result));
            },
            error : function(jqXHR, textStatus, errorThrown){
                console.log("Error ! Unable to get step " + number + " count." + "Error: " + errorThrown + ", Status: " + textStatus);
            }
        });
    }
}

ko.applyBindings(new chainModel());

Comments

0

Are you calling this method "get_total_count()" via any event binding. If so, then you can pass entire data view model to this method.

<input data-bind="event:{ click: function(data,event){ get_total_count(data,event,total_count()); } }" />

Comments

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.