Search code examples
javascriptaurelia

Binding to arbitrary or nonstandard attributes in Aurelia


In order to use a library, I need to be able to bind to the "for" attribute of a UL element.

This does not work:

<ul for="${id}"> ... </ul>

Based on testing I assume this is because ul elements don't normally have a for attribute. How do I work around this? This was a trivial in Durandal / knockout which I believed was something like:

data-bind="attr: { for: $data.id }"

Do I really have to create a custom attribute? Is this going to conflict with the built in attribute used for label? Any other obvious workaround?


Solution

  • Aurelia absolutely supports binding to ad-hoc/arbitrary properties on a DOM element.

    When you write <ul for="${id}"> ... </ul> Aurelia is going to assign the value of the id property to an ad-hoc property on the ul element.

    It's the equivalent of doing ul.for = id or ul['for'] = id.

    The part you're missing is setting an arbitrary property on a DOM element does not automagically create a corresponding HTML attribute. In other words, there's a difference between ul.for = id and ul.setAttribute('for', id). This is easy to forget because we typically work with standard html attributes and the DOM has special logic to mirror the value of the HTML attribute with the corresponding DOM property. This special logic does not exist for arbitrary properties that you might add in your code/bindings.

    You can force the binding to use setAttribute instead of the standard behavior by creating a binding behavior:

    https://gist.run/?id=feedfd7659d90c0bdf6d617a244288a6

    set-attribute.js

    import {DataAttributeObserver} from 'aurelia-binding';
    
    export class SetAttributeBindingBehavior {
      bind(binding, source) {
        binding.targetObserver = new DataAttributeObserver(binding.target, binding.targetProperty);
      }
    
      unbind(binding, source) {}
    }
    

    usage:

    <template>
      <require from="./set-attribute"></require>
    
      <ul for.bind="id & setAttribute"></ul>
    
      <ul for="${id & setAttribute}"></ul>
    </template>
    

    EDIT

    Aurelia now ships with an attr binding behavior. Use <ul for="id & attr">. Here's the updated example: https://gist.run/?id=5a12f928d66b6d92c592feb6a62940ad