Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Duplicate "id" attribute in Angular 2 component

Context

I'm writing a custom Angular component for a checkbox. The component renders a checkbox tag along with a label tag. The "id" attribute of the checkbox and the "for" attribute of the label are both set to the component's id property (an @Input to the component) to ensure that clicking the label will toggle the checkbox. A simplified version of the template looks like:

<div class="checkbox">
    <input type="checkbox" [id]="id" />
    <label [for]="id"><ng-content></ng-content></label>
</div>

Problem

When I set an "id" prop on my component (e.g. <my-checkbox id="hello">Check me</my-checkbox>), an "id" attribute is automatically set on the component wrapper tag in the DOM. This results in duplicate ids in the DOM because I'm already setting an "id" attribute on the checkbox inside the component. This is invalid and breaks the browser's default toggle-by-clicking-the-label behavior. The DOM output is:

<my-checkbox id=“my-checkbox” ng-reflect-id=“my-checkbox” ng-reflect-checked="true">
    <div ng-reflect-ng-class="[object Object]" class="checkbox">
        <input class="checkbox__element" type="checkbox" name="fire_missiles" ng-reflect-id=“my-checkbox” id=“my-checkbox” value=“fire_missiles” ng-reflect-checked="true">
        <label class="checkbox__label" ng-reflect-html-for=“my-checkbox” for=“my-checkbox”>
            Fire missiles?
        </label>
    </div>
</my-checkbox>

Is there a way to either a) get rid of the garbage container tag or b) stop the automatic reflection of the "id" prop onto the container as an attribute?

NOTE: Using an attribute selector applied to something like a div doesn't help, it just moves the extra "id" from <my-checkbox /> to the div.

like image 601
Elliot Avatar asked Jan 05 '17 22:01

Elliot


2 Answers

You can pass id as expression:

<my-checkbox [id]="'hello'">Check me</my-checkbox>

In this case component tag does not contain id attribute in DOM, it contains only attribute ng-reflect-id, which does not affect default behavior for label.

like image 144
Yuri Beliakov Avatar answered Oct 23 '22 15:10

Yuri Beliakov


I would simply rename the checkbox's id (and hence the label's for attribute) so that it doesn't clash with the component's id, like so:

<input id="{{ id }}-checkbox" …>
<label for="{{ id }}-checkbox">…</label>
like image 9
balu Avatar answered Oct 23 '22 14:10

balu