Daniel
Daniel

Reputation: 3131

Why is this knockoutjs observableArray not causing UI update?

I have a feeling I'm missing something simple here, but just can't quite grok this. Here is my script:

function FormDefinition()
{
    var self = this;
    self.Fields = ko.observableArray([new FieldDefinition()]);    
}

function FieldDefinition()
{
    var self = this;
    self.Name = "Test";
}
function ViewModel()
{
    var self = this;
    self.formDef = ko.observable(new FormDefinition());
    self.Name = "bob"
    self.addField = function(){
        this.formDef().Fields().push(new FieldDefinition());                    
    }            
}

ko.applyBindings(new ViewModel());

and here is my markup:

<a data-bind="click: addField">Add</a><br/>
<span data-bind="text: Name"></span>
<ul data-bind="foreach: formDef().Fields">
    <li data-bind="text: Name"></li>
</ul>​

and here is a jsFiddle: http://jsfiddle.net/5xSmr/

Expected behavior is that clicking 'Add' would cause the ui to update. debugging reveals that addfield is getting called.

Upvotes: 15

Views: 15390

Answers (2)

AlexG
AlexG

Reputation: 4035

Fixed your fiddle: http://jsfiddle.net/5xSmr/2/

<a data-bind="click: AddField">Add</a><br/>
<span data-bind="text: Name"></span>
<ul data-bind="foreach: formDef().Fields()">
    <li data-bind="text: Name"></li>
</ul>
function FormDefinition()
{
    var self = this;
    self.Fields = ko.observableArray();    
}

function FieldDefinition()
{
    var self = this;
    self.Name = "Test";
}
function ViewModel()
{
    var self = this;
    self.formDef = ko.observable(new FormDefinition());
    self.Name = "bob"
    self.AddField = function(){
        this.formDef().Fields.push({Name:"test"});
    }            
}

ko.applyBindings(new ViewModel());

The main problem was that you were calling Fields() and not just Fields. Fields() return the unwrapped array and by pushing directly to it, ko would never know about it.

Upvotes: 30

Jason More
Jason More

Reputation: 7073

Here you go :-)

http://jsfiddle.net/JasonMore/Q6J6a/3/

View

<a href='#' data-bind="click: AddField">Add</a><br/>
<span data-bind="text: Name"></span>
<ul data-bind="foreach: formDef.Fields">
    <li data-bind="text: Name"></li>
</ul>​

Javascript

var FormDefinition = function ()
{
    var self = this;
    self.Fields = ko.observableArray();    
}

var ViewModel = function()
{
    var self = this;
    self.formDef = new FormDefinition();
    self.Name = ko.observable("bob");
    self.AddField = function(){
        self.formDef.Fields.push({Name:"test"});            
    }            
}

ko.applyBindings(new ViewModel());

Upvotes: 3

Related Questions