1

I am trying to make a radio-button filter that changes its background color when it's selected. Right now it looks like this:

           <div data-bind="visible: applications().length > 0">
                            <label>Filter: </label>
                            <label class="radio-inline">
                                <input type="radio" value="new" data-bind="checked: applicationsFilter, css: {selected: applicationsFilter}" class="" />
                                New / Pending Review
                                (<span data-bind="text: newApplicationsCount"></span>)
                            </label>
                            <label class="radio-inline">
                                <input type="radio" value="shortlisted" data-bind="checked: applicationsFilter, css: {selected: applicationsFilter}" />
                                Shortlisted
                                (<span data-bind="text: shortlistedApplicationsCount"></span>)
                            </label>
                            <label class="radio-inline">
                                <input type="radio" value="connected" data-bind="checked: applicationsFilter, css: {selected: applicationsFilter}}" />
                                Connected
                                (<span data-bind="text: connectedApplicationsCount"></span>)
                            </label>
                            <label class="radio-inline">
                                <input type="radio" value="all" data-bind="checked: applicationsFilter, css: {selected: applicationsFilter}" />
                                All
                                (<span data-bind="text: allApplicationsCount"></span>)
                            </label>
                            <label class="radio-inline" data-bind="visible: applications().length > 0">
                                <input type="checkbox" data-bind="checked: showHiddenApplications" />
                                Include Hidden
                            </label>
                        </div>

My intention was to apply the .selected class when the radio-button is selected by doing

 data-bind="checked: applicationsFilter, css: {selected: applicationsFilter}}

But the output does not actually apply the css style. What is the proper way of doing this?

Thanks

1 Answer 1

3

The correct way to do this is by making an actual comparison that evaluates to true or false:

css: {selected: applicationsFilter() == 'new'}

But you might also run into the issue that - especially Firefox, but other browsers as well - ignore styles on radio buttons.

One option would be to use the css binding on the label instead of the input.

Another would be to make separate inputs+labels, instead of nested ones, and use CSS to react to the :checked state. The following uses the very helpful uniqueId and uniqueFor custom bindings by RP Niemeyer.

// uniqueId/uniqeFor custom bindings by @RPNiemeyer, https://stackoverflow.com/a/9235013/18771
ko.bindingHandlers.uniqueId = {
    init: function(element, valueAccessor) {
        var value = valueAccessor();
        value.id = value.id || ko.bindingHandlers.uniqueId.prefix + (++ko.bindingHandlers.uniqueId.counter);

        element.id = value.id;
    },
    counter: 0,
    prefix: "unique"
};

ko.bindingHandlers.uniqueFor = {
    init: function(element, valueAccessor) {
        var value = valueAccessor();
        value.id = value.id || ko.bindingHandlers.uniqueId.prefix + (++ko.bindingHandlers.uniqueId.counter);

        element.setAttribute("for", value.id);
    } 
};


ko.applyBindings({
    applicationsFilter: ko.observable(),
    filterOptions: [
        {value: "new", label: "New / Pending Review"},
        {value: "shortlisted", label: "Shortlisted"},
        {value: "connected", label: "Connected"},
        {value: "all", label: "All"},
    ]
});
.radio-inline:checked+label {
    border: 1px solid red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<div data-bind="foreach: filterOptions">
    <input type="radio" class="radio-inline" data-bind="value: value, checked: $parent.applicationsFilter, uniqueId: $data" />
    <label data-bind="text: label, uniqueFor: $data"></label>
</div>

<pre data-bind="text: ko.toJSON($root, null, 2)"></pre>

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

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.