Skip to content
kamranayub edited this page Mar 22, 2013 · 7 revisions

This binding allows you set an arbitrary css class for an element. It requires jQuery.

    ko.bindingHandlers['class'] = {
        'update': function(element, valueAccessor) {
            if (element['__ko__previousClassValue__']) {
                $(element).removeClass(element['__ko__previousClassValue__']);
            }
            var value = ko.utils.unwrapObservable(valueAccessor());
            $(element).addClass(value);
            element['__ko__previousClassValue__'] = value;
        }
    };

Here's an alternate version that uses Knockout only (no jQuery):

    ko.bindingHandlers['class'] = {
        'update': function(element, valueAccessor) {
            if (element['__ko__previousClassValue__']) {
                ko.utils.toggleDomNodeCssClass(element, element['__ko__previousClassValue__'], false);
            }
            var value = ko.utils.unwrapObservable(valueAccessor());
            ko.utils.toggleDomNodeCssClass(element, value, true);
            element['__ko__previousClassValue__'] = value;
        }
    };

Example:

    <table>
        <tbody data-bind="foreach: datasets">
            <tr data-bind="class: rowClass">
                <td data-bind="text: title"></td>
                <td data-bind="text: dataCount"></td>
            </tr>
        </tbody>
    </table>

Here's a demonstration fiddle and an expanded fiddle comparing it to attr (thanks Koviko).

Observable Array support

Here's an example of the binding which accepts either a single observable or an observable array:

//
// Observable CSS Class Binding
//
ko.bindingHandlers['class'] = {
    update: function (element, valueAccessor) {
        var currentValue = ko.utils.unwrapObservable(valueAccessor()),
            prevValue = element['__ko__previousClassValue__'],
            
            // Handles updating adding/removing classes
            addOrRemoveClasses = function (singleValueOrArray, shouldHaveClass) {
                if (Object.prototype.toString.call(singleValueOrArray) === '[object Array]') {          
                    ko.utils.arrayForEach(singleValueOrArray, function (cssClass) {
                      var value = ko.utils.unwrapObservable(cssClass);
                      ko.utils.toggleDomNodeCssClass(element, value, shouldHaveClass);
                    });
                } else if (singleValueOrArray) {
                    ko.utils.toggleDomNodeCssClass(element, singleValueOrArray, shouldHaveClass);
                }
            };
        
        // Remove old value(s) (preserves any existing CSS classes)
        addOrRemoveClasses(prevValue, false);
        
        // Set new value(s)
        addOrRemoveClasses(currentValue, true);
        
        // Store a copy of the current value
        element['__ko__previousClassValue__'] = currentValue.concat();
    }
};

Here's an example Fiddle illustrating its use.