Conditionally add an element attribute in knockout.js

Javascriptknockout.js

Javascript Problem Overview


The knockout.js library has an "attr" data binding which allows you to dynamically change the value of an HTML element attribute (e.g. the "title"). However, in some cases, the attribute may or may not be needed depending on the corresponding observable on the bound object. For example, if my model has a "title" observable I might want to set the "title" attribute if it is present (non-null) or skip the attribute entirely if it is not present (null).

Does knockout provide any way to conditionally set an attribute? (Ideally without conditionally rendering the entire element opening tag...)

[Note] This similarly named question was actually resolved by knockout's special handling of CSS classes and does not relate to this question (or its own title): https://stackoverflow.com/questions/11014336/how-to-conditionally-render-an-html-attribute-with-knockoutjs

Javascript Solutions


Solution 1 - Javascript

I needed this when selecting an <option> (that I was generating manually instead of built-in knockout).

<option 
 data-bind="text: text, 
    attr:{
     value:value,
     'selected': typeof(selected) !== 'undefined' ? selected : null 
     }">
 Choice X
</option>

This says to always update the 'text' attribute and to add the 'value' attribute, but only add 'selected' if the the data already has a value of 'selected' defined.

Solution 2 - Javascript

You can create a custom binding attrIf which will check the value of a specific observable boolean before add or not the attributes. See this example:

ko.bindingHandlers.attrIf = {
    update: function (element, valueAccessor, allBindingsAccessor) {
        var h = ko.utils.unwrapObservable(valueAccessor());
        var show = ko.utils.unwrapObservable(h._if);
        if (show) {
            ko.bindingHandlers.attr.update(element, valueAccessor, allBindingsAccessor);
        } else {
            for (var k in h) {
                if (h.hasOwnProperty(k) && k.indexOf("_") !== 0) {
                    $(element).removeAttr(k);
                }
            }
        }
    }
};

<a href="#" data-bind="attrIf: {title: title, _if: flag}">link</a>

Solution 3 - Javascript

>Knockout's "attr" data binding does support this scenario just return null or undefined from your getDisabledState() function then it won't emit the attribute.

This answer was retrieved from https://stackoverflow.com/questions/14165213/knockout-attr-binding-with-attributes-like-readonly-and-disabled

Solution 4 - Javascript

I wish I could have just replied to @gbs, but I can't. My solution would have been to have two of the same HTML element, one with the attribute, one without, and a knockout condition to add one of it according to the element. I also know about this custom biding, but which of the solution is more efficient?

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionmaericsView Question on Stackoverflow
Solution 1 - JavascriptJJ RohrerView Answer on Stackoverflow
Solution 2 - JavascriptgbsView Answer on Stackoverflow
Solution 3 - JavascriptzshiftView Answer on Stackoverflow
Solution 4 - JavascriptLavinia Andreea CojocaruView Answer on Stackoverflow