RFC idea: template scoped unique IDs

In my forms I often want to reference elements by ID (per the spec). To do so in a component however comes with the caveat that HTML IDs are global and to make then unique for each instance of a component we have to do some contortions to support this.

There are many ways to solve this problem so I will focus on the one solution I use all the time—

{{#let (guid-for this "name") as |id|}}
  <label for={{id}}>Name</label>
  <input id={{id}}>
{{/let}}

This example creates a unique ID that can be shared for the <label> and the <input>. Another example—

{{#let (guid-for this "form") as |formId|}}
  <ModalDialog as |modal|>
    <modal.Header>…</modalHeader>

    <modal.Content>
      <form id={{formId}}>
        …
      </form>
    </modal.Content>

    <modal.Footer>
      <button type="submit" form={{formId}}>
        Save and Close
      </button>
    </modal.Footer>
  </ModalDialog>
{{/let}}

With both these cases it means we have to wrap things with a #let and create our own guid-for helper.—

{{#let (guid-for this "first-name") as |id|}}
  <label for={{id}}>First Name</label>
  <input id={{id}}>
{{/let}}
{{#let (guid-for this "last-name") as |id|}}
  <label for={{id}}>Last Name</label>
  <input id={{id}}>
{{/let}}

All this leads me to want a cleaner and fresher way to perform this common task. I’d like to propose an idea and see if other feel this is worth bringing to the core team as an RFC.

<label for={{@@name}}>Name</label>
<input id={{@@name}}>

Or perhaps a new sigil—

<label for={{^name}}>Name</label>
<input id={{^name}}>

And what this would do is internally convert the value into a unique ID that remains the same for the scope of that component’s template.

Component A
  @@foo => 'uniqueID-A-foo'
  @@foo => 'uniqueID-A-foo'
  @@bar => 'uniqueID-A-bar'
Component B
  @@foo => 'uniqueID-B-foo'
  @@foo => 'uniqueID-B-foo'
  @@bar => 'uniqueID-B-bar'

Thoughts?

1 Like

Have you seen this RFC (on exactly this subject)?

I think my idea expands on that semantics a bit more then just a helper.

In the first case of the label/input we also have to make the as |id1| unique because eslint complains if we attempt to use multiple #let

This seems just like a bug to me, reusing that id block param should be totally fine! Also, I assume you mean ember-template-lint (not eslint)? If so would you mind filing an issue?

1 Like

Unable to reproduce. Must have been an old bug. Edited original post.