Linking input and label inside custom element

I am trying to replace all occurences of this piece of html (using Bootstrap 4 framework):

<div class="form-check">
    <input type="checkbox" checked.bind="" class="form-check-input" id="foo-checkbox-input">
    <label class="form-check-label" for="foo-checkbox-input">My FOO</label>

<div class="form-check">
    <input type="checkbox" checked.bind="" class="form-check-input" id="bar-checkbox-input">
    <label class="form-check-label" for="bar-checkbox-input">My BAR</label>

with custom elements:

<input-checkbox checked.bind="" id="foo-checkbox-input" label="My FOO"></input-checkbox>
<input-checkbox checked.bind="" id="foo-checkbox-input" label="My FOO"></input-checkbox>

So, here is my view-model:

import { bindable, bindingMode } from ‘aurelia-framework’;

export class InputCheckbox {
    @bindable public id: any;
    @bindable public label: any;
    @bindable({ defaultBindingMode: bindingMode.twoWay }) public checked: any;

and my view:

    <div class="form-check">
        <input type="checkbox" checked.bind="checked" class="form-check-input" id.bind="id">
        <label class="form-check-label" for.bind="id">${label}</label>

But the checkboxes aren’t working, like if the inputs don’t have ID’s and labels don’t have FOR filled.
If I change my custom element template to this:

    <div class="form-check">
        <input type="checkbox" checked.bind="checked" class="form-check-input" id="WRONG">
        <label class="form-check-label" for="WRONG">${label}</label>

then the checkbox works, but of course not properly when I have more than 1 custom checkbox.

How do I link the input[checkbox] and the label inside my custom element?

If inside repeat.for you can id.bind="${‘my-checkbox-id’+$index}" with the same for for.bind

Another way we achieved the same thing was to create a “id generator” service, which basically just handed out identities (in our case, monotonically increasing numbers, but it could be anything unique).

export class IdService {
    private currentId;
        this.currentId = 0;

        return this.currentId++;

Then every control that needs some sort of unique ID for the entire page can get this service, call getId(), and bind to that.

It’s a little easier than remembering to pass in a unique ID from each parent.

Side note: In Aurelia, Everything is an application-level singleton except for those things which are classified as “components”, so you don’t need to worry about multiple instances of this service.

1 Like

Thanks for your answer, Alexander.

I think you have misundertood my problem, I am talking about html “for” attribute, and not the aurelia “repeat.for”.

Here is the reference:

Thanks thinkOfaNumber, but my problema isn’t getting an unique ID, since my intention is to provide it . Something like

<input-checkbox id="first" checked.bind="foo" label="First checkbox"></input-checkbox>
<input-checkbox id="second" checked.bind="bar" label="Second checkbox"></input-checkbox>

Do you have to provide it? But I think that’s a separate question!

This should work exactly as you’ve written it:

however here, you’re using the same id for both. You’d need to provide a unique ID:

If that’s just a copy-pasta error, then maybe reproduce this on I’ve definitely bound id and for attributes like you’re doing, so it should work.

Ops, yes, it was a copy & paste error. Those id’s should be different.

Are you able to make a gist?

Sure, here it is:

You can see the checked.bind working when clicking directly on the checkboxes inputs.
However, clicking on the blue labels doesn’t trigger the checkbox “click” action, as expected when you have a <label for="checkbox-id">

Made some progress. This gist runs perfectly:

The trick was to use a “-internal” suffix for the id of the checkbox (to not repeat the id of the custom element itself).

However, the checkbox is not working in my project, with bootstrap 4. Have to investigate it.

If I forked it right you should be able to try this:

Essentially I renamed the ID property. I’m not sure why it was making this odd behaviour, but if you name it to my-id, it works!

[edit] Snap! looks like we both got a solution… interesting…

1 Like