I just upgraded to knockout.js 2.2.0 and a foreach statement isnt working anymore with a computed observable. If I switched back to 2.1 it works. The computed observable updatedValues doesnt repopulate the foreach in the html below. Keep in mind the html below is dynamically inserted into the dom on a single ajax page and applied bindings.
ko.bindingHandlers.fields = {
init: function (element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
app.viewModel.members.meta = {
values: ko.observableArray(value.values),
remove: function () {
app.viewModel.members.meta.values.remove(this);
return false;
},
add: function () {
app.viewModel.members.meta.values.push({ Name: '', Value: '', Index: ko.observable(app.viewModel.members.meta.values().length) });
return false;
},
max: value.max
};
app.viewModel.members.meta.updatedValues = ko.computed(function () {
if (this.values()) {
for (var i = 0; i < this.values().length; i++) {
if (this.values()[i].Index)
this.values()[i].Index(i);
else
this.values()[i].Index = ko.observable(i);
}
}
return this.values;
}, app.viewModel.members.meta);
}
};
<div class="control-group">
@Html.LabelFor(q => q, "Custom Fields")
<div class="controls">
<div class="meta" data-bind="fields: { values: @Model.Meta.OrderBy(q => q.Name).ToJSON(), max: @Model.MaxCount }">
<div data-bind="foreach: members.meta.updatedValues">
<div class="form-inline">
<div class="input-prepend">
<span class="add-on">Name</span>
@Html.TextBox("Key", string.Empty, new { maxvalue = "100", data_bind = "value: Name, attr: { name: '" + Model.PropertyName + "[' + Index() + '].Name', id: '" + Model.PropertyName + "[' + Index() + '].Name' }" })
</div>
@if(!Model.HideValues)
{
<div class="input-prepend">
<span class="add-on">Value</span>
@Html.TextBox("Value", string.Empty, new {data_bind = "value: Value, attr: { name: '" + Model.PropertyName + "[' + Index() + '].Value', id: '" + Model.PropertyName + "[' + Index() + '].Value' }"})
</div>
}
<a href="#" class="btn btn-mini btn-danger" title="Remove Field" data-bind="click: $parent.members.meta.remove"><i class="icon-minus icon-white"></i></a>
</div>
</div>
<div class="control-group">
@Html.Button("New Field", new { type="button", @class="btn", data_bind = "click: members.meta.add, visible: members.meta.max >= members.meta.values().length" })
@Html.Partial(MVC.Shared.Views.Controls.Help, new HelpModel { Url = Url.Action(Model.ActionResult ?? MVC.Members.Dashboard.CustomFieldsHelp()), Title = Model.Title ?? "Custom Fields" })
</div>
</div>
</div>
</div>
Have a look about the updates done here Knockout 2.2.0 released.
foreach and template enhancements
I think that computed should be returning a plain array so change it to
values: []because in Knockout 2.2 there is no twice-unwraping of the observables when using
foreach().You can always log an issue here: https://github.com/SteveSanderson/knockout/issues