3

I'm binding a ko.observablearray to a table. Each object (called a 'group') in the array is bound to a table. Each group holds another (non-knockout) array of codes. Each code is bound to a row. Each code has a boolean, bound to a checkbox.

If none of the booleans are true in a group, I want all the checkboxes for that group to be enabled. If at least one of the booleans are true in a group, I want the false checkboxes for that group to be disabled, and the true checkboxes to be enabled. When the page is loaded, this works as expected; however, when I check or uncheck a box, the enabled/disabled status of the boxes does not change. Looking at it with the debugger, the observablearray is being updated, but the data in the table is not.

Page:

<table data-bind="foreach: {data: Groups}">
    <thead>
        <tr>
            <th colspan="3" data-bind="text: GroupName"></th>
        </tr>
    </thead>
    <tbody data-bind="foreach: {data: Codes}">
        <tr>
            <td data-bind="text: CodeId"></td>
            <td data-bind="text: Desc"></td>
            <td>
                <input type="checkbox" data-bind="checked: Prime, disable: $root.HasPrime($parent) && !Prime" />
            </td>
        </tr>
    </tbody>
</table>

Javascript function that tests if there are any true values in a group:

var HasPrime = function (gr) {
    for (var i = 0; i < gr.Codes.length; i++) {
        if (gr.Codes[i].Prime === true) {
            return true;
        }
    }
    return false;
};

Fiddle: http://jsfiddle.net/NSLPu/2/

ATayloe
  • 170
  • 7

1 Answers1

3

If you want two-way binding you'll need to make things observable. In your case, the Prime properties have to be observables:

var code1 = {
    'CodeId': 123,
        'Desc': 'Code 1',
        'Prime': ko.observable(false) // <---- changed!
};

This will require some corresponding changes in the rest of your code:

  • Plain JS calls have to invoke Prime as a method to get the current value
  • Bindings that "do stuff" (like negation, as on the input) will also need to invoke the observable to get the value negated

See this fiddle for an update.

Jeroen
  • 60,696
  • 40
  • 206
  • 339
  • I must have missed where observablearrays only worked as one-way bindings. Thanks! – ATayloe Aug 13 '13 at 19:42
  • The *array itself* is two-way: if you add or remove items it'll update the UI automatically. The *items* in the array are another matter though. – Jeroen Aug 13 '13 at 19:43