7

For some attributes, it is the presence of the attribute that has an effect - the value that is assigned to it is irrelevant. For example, the autofocus attribute can be set to 'false' or 'true, or 'banana' and the element is still gets automatically focused. IE, the following are all equivalent and cause the div to get focus :

<div autofocus="false" contenteditable="true"></div>
<div autofocus="true" contenteditable="true"></div>
<div autofocus="banana" contenteditable="true"></div>

Knockout has an 'attr' binding, but it seems to be only useful for assigning values to attributes, not for adding/removing attributes.

Is there another way to do it in knockout, or am I forced to set it from javascript?

NB Using chrome on ubuntu.

Max Waterman
  • 499
  • 6
  • 13
  • @Evan Kroske have you seen this question http://stackoverflow.com/questions/14165213/knockout-attr-binding-with-attributes-like-readonly-and-disabled?rq=1? – nemesv Apr 20 '13 at 18:07
  • 1
    @Evan Kroske The attr binding DOES remove the attribute if the observable value is strictly false, null, or undefined. See this test https://github.com/SteveSanderson/knockout/blob/master/spec/defaultBindings/attrBehaviors.js#L42-52 – nemesv Apr 23 '13 at 05:07
  • @nemesv Make your comment an answer, and I'll accept it. – Evan Kroske Apr 25 '13 at 13:29
  • @EvanKroske I think badsyntax's answer covers the same ground... so you should accept that. Maybe edit in my link... – nemesv Apr 25 '13 at 19:38

4 Answers4

6

Use a boolean false value to remove the attribute, use a string 'false' to set the attribute. What more do you need?

eg:

// Set as boolean, removes the attribute
autofocus(false);   

// Set as boolean, adds the attribute
autofocus(true);  

// Set as string, adds the attribute
autofocus('false');   

// Set as string, adds the attribute
autofocus('true');   

See here for an example: http://jsfiddle.net/badsyntax/XMDFh/

badsyntax
  • 9,394
  • 3
  • 49
  • 67
  • 2
    Your answer is correct, but I think your description could be clearer and nicer, and the code in the answer doesn't contain all the details one would need to understand the answer. If JSFiddle went away, your code wouldn't be very helpful. – Evan Kroske Apr 26 '13 at 19:58
1

You can use hasfocus knockout binding:

<input data-bind="hasfocus: isSelected" />

Read more here: http://knockoutjs.com/documentation/hasfocus-binding.html

Artem Vyshniakov
  • 16,355
  • 3
  • 43
  • 47
  • ok, but is there not a general solution for adding/removing attributes? ...or perhaps autofocus is somewhat unique in this respect (I notice contenteditable doesn't behave this way)? – Max Waterman Oct 08 '12 at 12:57
  • attr binding works the same way as hasfocus but for any attribute. – Artem Vyshniakov Oct 08 '12 at 13:03
  • but it seems not - attr sets the attribute to a value, but can't remove it completely. I'm having a similar issue with the style binding now - I want to set 'text-overflow' to 'ellipsis', or not have it at all, but there's no option to not have it at all. – Max Waterman Oct 10 '12 at 08:08
  • nb 'text-overflow' has a default value, so I can set it to that and it has the same effect as it not being there at all. – Max Waterman Oct 11 '12 at 03:49
0

You can write a kohandler that removes attributes using jquery.

segFault
  • 1,228
  • 2
  • 18
  • 41
0

There is not a native binding in Knockout to add or remove an attribute, only to set an attribute.

The reason why the hasFocus binding exhibits the behavior it does is because it uses an element's native .focus() and .blur() methods to add or remove focus.

Knockout having difficulty managing non-boolean attributes has been reported before, here's one example where Michael Best mentioned it would not be addressed:

https://github.com/SteveSanderson/knockout/issues/391

Update:

You could create a binding handler along these lines:

ko.bindingHandlers.toggleAttr = {    
    update: function (element, valueAccessor) {    
        var options = ko.utils.unwrapObservable(valueAccessor());
        var attr = ko.utils.unwrapObservable(options.attr);
        var param = ko.utils.unwrapObservable(options.param);

        param ? element.setAttribute(attr, true) : element.removeAttribute(attr);        
    }
};

Which would allow you to do this:

<input data-bind="toggleAttr: { attr: 'autofocus', param: focusMe }" />

Here's a fiddle: http://jsfiddle.net/nathanjones/9EzBD/

Nathan Jones
  • 950
  • 14
  • 22
  • The attr binding DOES remove the attribute if the observable value is strictly false, null, or undefined. See this test https://github.com/SteveSanderson/knockout/blob/master/spec/defaultBindings/attrBehaviors.js#L42-52 – nemesv Apr 23 '13 at 05:07