1

I have a checkbox that is bound to a property on my object used in my observableArray. I can't get the checkboxes to update correctly when clicked. The value doesn't set correctly nor does the checkbox uncheck itself when i click it. The example bindings have a property on the ViewModel directly rather then a property of an object used inside of the ViewModel. Can anyone shed light on how to get this working?

            <tbody id="StatusGrid" data-bind="foreach:{data: Statuses, as: 'status'}">
            <tr data-bind="attr: { index: $index }" style="padding-bottom:5px;">
                <td style="padding-bottom:5px;">
                    <input class="statusID" data-bind="value: status.StatusID, visible: status.ShowID, attr: { name: 'Statuses[' + $index() + '].StatusID'}" />
                </td>
                <td style="padding-bottom:5px;">
                    <input class="description" data-bind="value: status.Description, attr: { name: 'Statuses[' + $index() + '].Description'}" />
                </td>
                <td style="padding-bottom:5px;">
                    <input type="checkbox" class="active" data-bind="value: status.Active, checked: status.Active, click: $parent.updateCheckbox, attr: { name: 'Statuses[' + $index() + '].Active'}" />
                </td>
                <td style="padding-bottom:5px;">
                    <input type="button" data-bind="click: $parent.removeStatus, visible: status.IsNew" value="Remove" />
                </td>
            </tr>
        </tbody>


 //////KNOCKOUT//////
var _viewModel = new ViewModel();

function status(index) {
    this.StatusID = ko.observable('');
    this.Description = ko.observable('');
    this.Index = ko.observable(index);
    this.Active = ko.observable(true);
    this.ShowID = ko.observable(false);
    this.IsNew = ko.observable(true);
    return this;
};

function ViewModel() {
    var self = this;

    self.Statuses = ko.observableArray(convertJSONToKoObservableObject());
    //self.Statuses.push(new status(0));

    //Ko Functions
    self.addStatus = function () {
        var index = $('#StatusGrid tr:last').attr('index');
        self.Statuses.push(new status(index + 1));
    }

    self.removeStatus = function (row) {
        self.Statuses.remove(row);
    }

    self.updateCheckbox = function (row) {
        var index = row.Index();
        var checkbox = $('#StatusGrid tr').eq(index).find('[type=checkbox]');
        if ($(checkbox).is(":checked")) {
            $(checkbox).attr('checked', false);
            row.Index(false);
        }
        else {
            $(checkbox).attr('checked', true);
            row.index(true);
        }
        return true;
    }
}

//FUNCTION
function convertJSONToKoObservableObject() {
    var json = JSON.parse('@Html.Raw(new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(Model.Statuses))');
    var ret = [];
    var index = 0;
    $.each(json, function (i, obj) {
        var newOBJ = new status(index);
        newOBJ.StatusID = ko.observable(obj["StatusID"]);
        newOBJ.Description = ko.observable(obj["Description"]);
        newOBJ.Active = ko.observable(obj["Active"]);
        newOBJ.Index = ko.observable(index);
        newOBJ.ShowID = ko.observable(false);
        newOBJ.IsNew = ko.observable(false);
        ret.push(newOBJ);
        index++;
    });

    return ret;
}

//BIND UP!
ko.applyBindings(_viewModel);

3 Answers 3

2

You can use an if binding, so:

<td style="padding-bottom:5px;">
<span data-bind="if: status.Active"> 
   <input type="checkbox" data-bind="value: status.Active" checked/>
</span>
<span data-bind="ifnot: status.Active"> 
   <input type="checkbox" data-bind="value: status.Active" />
</span>
</td>

It may not be pretty, but it works instead of using 2x 2-way binding together (namely, value and checked binding together), which does not seem to give you your typical checkbox behaviour. ...

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

Comments

0

I think may be the value binding is interfering with the checked binding

<input type="checkbox" class="active" data-bind="value: status.Active, checked: status.Active, click: $parent.updateCheckbox, attr: { name: 'Statuses[' + $index() + '].Active'}" />

Try it with the checked binding only I believe knockout keeps the observable in sync

<input type="checkbox" class="active" data-bind="checked: status.Active, click: $parent.updateCheckbox, attr: { name: 'Statuses[' + $index() + '].Active'}" />

If I understand your code correctly, I also doubt you need to check/uncheck the checkbox using jQuery, knockout should handle the checking and updating the observable automatically by using the checked binding

1 Comment

I updated the binding by removing the value: and it began to start unchecking/checking the box correctly. However, now the value's do not post back to my controller. If you notice the attr{name} bindings, it is following the mvc binding scheme for the mvc model to retain values on postback. All the others work fine but it appears removing the value: binding caused it lose the values on the form post.
0

After making the change suggested and then tweaking the html further for the mvc post. Below works for the check binding and the value binding for the post back :)

                        <input type="checkbox" class="active" data-bind="checked: status.Active" />
                    <input type="hidden" data-bind="value: status.Active, attr: { name: 'Statuses[' + $index() + '].Active'}">

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.