Carl Weis
Carl Weis

Reputation: 79

Knockout JS binding not outputting values with simple view model

I'm trying to load up a simple view model that has two models, Profile which is a ko.observable() and requests, which is a ko.observableArray().

When I apply the bindings and then try to bind to ether profile.field or foreach: requests, I get no output, no javascript or binding errors. But when I dump out ko.toJSON(self.profile) or ko.toJSON(self.requests), I get in fact have the data, it's just not binding and I'm not sure why, any ideas what I'm doing wrong.

Here are my models

var Profile = function(profile) {   
    var self = this;

    self.id                  = ko.observable(profile.id);
    self.user_id             = ko.observable(profile.user_id);
    self.first_name          = ko.observable(profile.first_name);
    self.last_name           = ko.observable(profile.last_name);
    self.age                 = ko.observable(profile.age);
    self.email               = ko.observable(profile.email);
    self.area                = ko.observable(profile.area);
    self.favorite_restaurant = ko.observable(profile.favorite_restaurant);
    self.avatar              = ko.observable(profile.avatar);
    self.on_mailing_list     = ko.observable(profile.on_mailing_list);
}
var Request = function(request) {
    var self = this;

    self.id           = ko.observable(request.id);
    self.user_id      = ko.observable(request.user_id);
    self.title        = ko.observable(request.title);
    self.participants = ko.observable(request.participants);
    self.food_type    = ko.observable(request.food_type);
    self.event_date   = ko.observable(request.event_date);
    self.time_of_day  = ko.observable(request.time_of_day);
    self.area         = ko.observable(request.area);
    self.description  = ko.observable(request.description);
    self.status       = ko.observable(request.status);
}

Here is my ViewModel

var MasterViewModel = function() {
    var self = this;

    self.profile       = ko.observable();
    self.requests      = ko.observableArray();
    self.notifications = ko.observableArray();

    // load the users profile 
    $.getJSON('/profiles/load', {}, function(profile) {     
        self.profile = new Profile(ko.toJS(profile));
        console.log(ko.toJSON(self.profile));

        // load the users requests
        $.getJSON('/request/load', {}, function(requests){
            var mappedRequests = $.map(requests, function(request) {
                return new Request(request);
            });
            self.requests = mappedRequests;
            console.log(ko.toJSON(self.requests));
        });         
    });
}

Here are the simple bindings I'm trying to apply

<h2 data-bind="text: profile.first_name"></h2>

<ul data-bind="foreach: requests">
    <li data-bind="text: title"></li>
</ul>

And of course I'm applying the knockout bindings in document ready

  <script>
    $(document).ready(function() {
      // bind the ViewModel
      ko.applyBindings(new MasterViewModel());
    });
 </script>

Upvotes: 1

Views: 817

Answers (2)

you need to update the value of the observables and not it's references. Also you will need to access the profile value as a function

<h2 data-bind="text: profile().first_name">

check this fiddle http://jsfiddle.net/victorrseloy/qFnUC/1/

    var i = 0;

function Profile(){
    var self = this;
    this.first_name = ko.observable("profile"+(i++));
}

function ViewModel(){
    this.profile= ko.observable(new Profile());
    this.requests= ko.observableArray([{title:"t1"},{title:"t2"}]);
}


var viewModel = new ViewModel()

function changeReference(){

    viewModel.profile = new Profile();
    viewModel.requests = [{title:"t1"+i},{title:"t2"+i}];

}

function changeValue(){
   viewModel.profile(new Profile());
   viewModel.requests([{title:"t1"+i},{title:"t2"+i}]);
}

ko.applyBindings(viewModel)

html:

<h2 data-bind="text: profile().first_name"></h2>

<ul data-bind="foreach: requests">
    <li data-bind="text: title"></li>
</ul>
<a href="#" onclick="changeReference()">change reference</a>
<a href="#" onclick="changeValue()">change value</a>

Upvotes: 0

Damien
Damien

Reputation: 8987

You should set the observables not override them with a new value.

You wrote :

self.profile = new Profile(ko.toJS(profile));

You should write this :

self.profile(new Profile(ko.toJS(profile)));

Why? Because this way, ko knows that the profile changed and it has to refresh the view.

Same problem with :

self.requests = mappedRequests;

which should be :

self.requests(mappedRequests);

Upvotes: 1

Related Questions