I want to get the below checkbox element in ts to manipulate its value (checked = true)
<div class="input-wrapper" *ngFor="let i of rolesData">
<input type="checkbox" name="{{i.role}}" id="{{i.role}}" class="selectedRole">
<label for="{{i.role}}">{{i.role}}</label>
</div>
i.role
is 'Software Developer'. Now the following code inside ngOnInit
prints null
.
console.log("element", document.getElementById('Software Developer'))
Please help.
The reason why it prints undefined
as ngOnInit
is triggered when Angular initializes a component or directive.
For your scenario, you need ngAfterViewInit
which this event is triggered after Angular renders the view. So that you can get the element from the view.
ngAfterViewInit() {
console.log('element', document.getElementById('Software Developer'));
}
Reference: Responding to view changes
Updated
According to your requirement that the roleData
is fetched from Observable which is asynchronous. Meanwhile the ngAfterViewInit
is the event that is triggered when Angular initializes the view but not when the view is completed.
Hence, to get the element from the view, it must be fulfilled with:
For the implementation as the code below:
With isDataFetchedSubject
Subject
, when it is completed, indicate that the roleData
observable is returned (isDataFetched$
).
With isViewRenderedSubject
Subject
, when it is completed, indicate that the view is rendered. And this requires the ngAfterViewChecked
lifecycle which is triggered when each time the view is rendered/changed (isViewRendered$
).
Requires the observables mentioned in 1 and 2 must be completed.
With the setTimeout
function to delay the function execution, continuously get the element from the view until the element is rendered.
isDataFetchedSubject: Subject<boolean> = new Subject<boolean>();
isDataFetched$ = this.isDataFetchedSubject.asObservable();
isViewRenderedSubject: Subject<boolean> = new Subject<boolean>();
isViewRendered$ = this.isViewRenderedSubject.asObservable();
ngOnInit() {
this.rolesData$.subscribe((value: any[]) => {
this.rolesData = value;
this.isDataFetchedSubject.next(true);
this.isDataFetchedSubject.complete();
});
forkJoin([this.isDataFetched$, this.isViewRendered$])
.pipe(takeUntil(this.destroyed$))
.subscribe(([flag1, flag2]) => {
console.log('Observable is completed');
if (flag1 && flag2) {
// Create a delay function to fetch element until it is existed
let checkElementExist = setTimeout((isExisted: boolean) => {
if (isExisted) clearTimeout(checkElementExist);
console.log(
'(2) element',
document.getElementById('Software Developer')
);
});
}
});
}
ngAfterViewChecked() {
this.isViewRenderedSubject.next(true);
this.isViewRenderedSubject.complete();
}