Using $index in a custom attribute under repeat.for

Hi,
I try to have an unique identifier per checkbox for testing purposes.
HTML template:

<ul>
    <li repeat.for="todo of todos>
        <input type="checkbox" checked.bind="todo.done" id="checkbox-$index">
    </li>
</ul>

View-model:

import {customAttribute} from 'aurelia-framework';
@customAttribute('id')
export class IdAttribute {}

But the string interpolation does not work. Could you tell me what is wrong with this sample?

1 Like

The sample code uses no string interpolation at all, it should be id="checkbox-${$index}" or id.bind="'checkbox-'+$index"

4 Likes

I have already tried in such a way. But it does not work either.

1 Like

If you log

@customAttribute('id')
export class IdAttribute {
  valueChanged(newValue) {
    console.log('value:' + newValue);
  }
}

You will find both of @m-gallesio’s suggestion works. What does not work is that they don’t create the real id attribute on the input element itself. That’s what you tried to see when inspecting the element.

The reason is you provided a custom attribute on a standard attribute called id, which took over the default Aurelia behaviour.

Solution: remove your custom attribute implementation, let Aurelia to do its work. You will see Aurelia will populate the real id attribute with both suggestions from @m-gallesio.

4 Likes

I removed the id custom attribute ES class, and it works now. Thanks!

However it was just a first step. If I replace the id attribute in the HTML template with a test-id attribute without a matching view model class, I can notice:

  • The test-id is rendered if its value is static (ex.: test-id=“foo”).
  • The test-id is missing if its value needs a string interpolation (ex.: test-id=“foo-${$index}”).
<ul>
    <li repeat.for="todo of todos>
        <input type="checkbox" checked.bind="todo.done" test-id="checkbox-${$index}">
    </li>
</ul>

So I create a test-id custom attribute ES class.

import {customAttribute} from 'aurelia-framework';

@customAttribute('test-id')
export class TestIdAttribute {

    valueChanged(newValue) {
       console.log('value: ', newValue);
    }
}

Now I can observe the following Aurelia behavior: all test-ids are present, but the $index is not valued in HTML. Any idea to achieve that?

1 Like

If you provide a custom attribute implementation, aurelia assumes you will play the value in your code.

It does not rewrite html attribute back to the node for most use cases.

Aurelia does write back attribute to the node on some special attributes. For example, id. This is designed to play nice with other 3rd party js lib which wants the real attribute on the node.

The other special attributes you can use are data- and aria- attributes. If you bind to data-id, aurelia will populate the attribute for you. This is also designed to play nice to other js libs. For example, bootstrap uses data- attributes as parameters of many features.

Again, don’t provide a custom attribute implementation for data-id.

2 Likes