2

I am using KnockoutJS for data binding. Following code is controller's action method

public JsonResult GetPeople()
{
    var people = new List<Person>
                     {
                         new Person {Name = "aaaa", Address = "aaaaaaaaa"},
                         new Person {Name = "bbbb", Address = "bbbbbbbbb"},
                         new Person {Name = "cccc", Address = "ccccccccc"}
                     };
    return Json(people, JsonRequestBehavior.AllowGet);
}

And bellow is the snippet of client side code

<ul data-bind="foreach: people">
  <li>NAME:<span data-bind="text: Name"></span></li>
  <li>ADDRESS:<span data-bind="text: Address"></span></li>  
</ul>

<script>
    function getPeopleFromServer() {
        var people= [];

        $.ajax({
            url: "GetPeople",
            cache: false,
            type: "GET",
            success: function (result) {
                console.log("result= " + result);
                people = $.parseJSON(result);
                console.log("people= " + people);
            }
        });

        return people;
    }

    function ViewModel() {
        var self = this;

        // data
        self.people = ko.observableArray(getPeopleFromServer());        
    }

    ko.applyBindings(new ViewModel());
</script>

The problem is that people variable in the getPeopleFromServer method is always null while result has proper value from the server. Am I missing something?

7
  • What do you get from console.log("result= " + result); Commented May 17, 2012 at 2:22
  • Have you checked to see if jQuery is parsing results as JSON for you? You might drop the $.parseJSON and see if things start working... Commented May 17, 2012 at 2:23
  • 1
    'success' is an inline async function. Basically, 'return people' happens before the 'success' function is called, because the ajax call is non-blocking. You need to redesign your ViewModel to work asynchronously (or turn off async), hopefully others will chime in with code fixes Commented May 17, 2012 at 2:25
  • I have log like this "result= [object Object],[object Object],[object Object] people= null" Commented May 17, 2012 at 2:44
  • @Tom regarding redesign viewmodel, what I want is to separate server invoke method from the viewmodel. Do you have any idea for that? Commented May 17, 2012 at 2:48

4 Answers 4

1

Your $.ajax function is taking longer to complete than it's containing function, and so the containing function never popuplates people by the end of execution

One thing you can do is to add the following to your $.ajax:

$.ajax({
   async: false,
   url: "GetPeople",
   .....
});

async: false will make the containing function 'wait' until ajax is finished. Your people var should be populated by the end of function execution. While this is a quick win, I agree with Tom that you should re-think how your ViewModel is handled.

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

1 Comment

thanks your reply Martin, I added "async: false", but the people is still null while result is not null.
0

@tom's comment is correct.

'success' is an inline async function. Basically, 'return people' happens before the 'success' function is called, because the ajax call is non-blocking. You need to redesign your ViewModel to work asynchronously (or turn off async), hopefully others will chime in with code fixes

Here's the fully commented fiddle he prophesied.

http://jsfiddle.net/bczengel/8Wqum/

Comments

0

people should be referred to either in the same view model. Or as self.people. I suggest you put the call to ajax inside the view model and then it will be clear. So getPeopleFromServer() should be inside the viewmodel.

Out of interest you can also add timeout: 600000 so that the call doesnt timeout.

Comments

0

Try to use ko.mapping plugin.

function ViewModelWrapper(jsonResult)
{
       var self = this;
       self.model = ko.mapping.fromJS(jsonResult);
}

http://knockoutjs.com/documentation/plugins-mapping.html

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.