Angular 2 unique id for every component instance of jQuery
Solution 1
Suppose you have a checkbox,
<input class="styled-checkbox" id="{{checkboxId}}" type="checkbox">
<label for="{{checkboxId}}">{{checkboxLabel}}</label>
import { Component, Input } from '@angular/core';
@Component({
selector: 'checkbox',
templateUrl: './checkbox.component.html'
})
export class CheckboxComponent {
@Input() checkboxId:string;
@Input() checkboxLabel:string;
}
in parent -->
<checkbox [checkboxId]="Math.random().toString(36).substring(2)"></checkbox>
Solution 2
Traversing the DOM: bad idea
You should not use jQuery to traverse the DOM and apply some transformations to it, here is why:
Jquery is tightly coupled with the DOM while angular tends to abstract all these interactions: when you modify the DOM in angular, you are supposed to use the Renderer
API that will apply transformations on the elements. This is what allows rendering on Workers, building nativescript applications, etc.
Some problem may occur if you want to traverse the DOM from a parent component to apply modifications :
- Some elements can be added to or removed from the DOM dynamically by the Angular renderer. How to deal with elements that are rendered conditionally ? traversing on every change detection is an anti-pattern.
- How to be sure the plugin you applied on an element has been properly destroyed when the element has been removed by the angular renderer ?
Sometimes you do need jQuery
If you do need to use jQuery, for example to apply a jQuery plugin on an element, it is a better practice to write a directive or a component and apply the plugin by adding the directive or component inside your template than traversing the DOM from a component.
You can create a directive like this :
NB: I have no idea of the full calendar API, so it is full improvisation.
@Directive({ selector: '[fullCalendar]' })
export class HighlightDirective implements OnInit,OnDestroy,OnChanges {
private jqElement:any;
constructor(private el: ElementRef) {
el.nativeElement.style.backgroundColor = 'yellow';
}
@Input()
options:any={};
ngOnInit(){
this.jqElement = $(this.el.nativeElement);
this.jqElement.fullCalendar(this.options);
}
ngOnChanges(changes:{[k:string]:SimpleChange}){
if(changes['options']&&!changes['options'].firstChange) // do not apply options on first change (jquery plugin not applied)
this.jqElement.fullCalendar("option",this.options);
}
ngOnDestroy(){
this.jqElement.fullCalendar("destroy");
}
}
and apply it this way:
<div fullCalendar [options]="someOptions"></div>
Solution 3
A simple and elegant solution (found it here)
let searchBoxId = 0;
@Component({
selector: 'app-auto-complete',
templateUrl: './auto-complete.component.html',
styleUrls: ['./auto-complete.component.less']
})
export class MyComponent implements AfterViewInit {
@Input() searchBoxId = `search-box-${searchBoxId++}`;
ngAfterViewInit(): void {
const searchBox = document.getElementById(`${this.searchBoxId}`);
// Get your input unique id
console.log("searchBox: ")
}
}
- Set a global variable
- Each time the component is being used (loaded) - we counter up the variable
- Make sure you get the unique id from the DOM, only after it has been loaded (ngAfterViewInit)
Comments
-
Amr Ibrahim almost 2 years
I have Angular 2 component contain jquery component and i want to generate id for every instance of my Angular 2 component because i need different jquery selector for each component
this is my component
@Component({ selector: 'full-calendar', templateUrl: 'full-calendar.html' }) export class FullCalendarComponent { ngOnChanges(changes: any) { $('angular2-fullcalendar').fullCalendar('option',changes.options.currentValue) } }
i want to use more than one with different selector each time
i found this solution
export class GetId { protected getId(id: number|string = _.uniqueId()): string { return _.lowerFirst(this.constructor.name) + '_' + id; } } class MyComponent extends GetId { ... }
and id can be used like this
<input [id]="getId('name')" type="text">
but i am still searching for built-in solution .
-
Amr Ibrahim about 7 yearsthank you for your explanation, i already implemented it this way . but question is not about this . question is about creating many component with different id. check the correct answer above
-
Celso Soares almost 5 yearshow can you guarantee that you will not get the same ID if this is a random id? Unless every time you generate a random id you check if this id already exist in the document. If yes, generate again... but dont think that this is the best practice.
-
Caltor over 4 yearsI used a slightly modified version of this to generate a
checkboxId
value in the typescript file that is then referenced as theid
for the checkbox andfor
in the label.