I searching for the correct way of accessing DOM elements in Angular.
I am working on an example, which requires access to the DOM elements, because I want to change the offsetTop
and the scrollTop
properties of my HTMLElements.
I managed to implement my desired feature by querying the DOM elements using document.querySelector('.my-query-class')
inside ngAfterViewInit()
. The only issue is that I am querying a div-element, which has a certain CSS class. The div-element, which has this CSS class, changes. This means: There are multiple div-elements, and their CSS class is given by [ngClass] = {'.my-query-class': condition}
. The condition changes upon clicking onto another div. So, I have to update the assignment myDOMElement = document.querySelector('.my-query-class')
inside a click-listener. I hope this is more or less clear. In my typescript file I am basically doing the following:
myDOMelement?: HTMLElement;
ngAfterViewInit() {
myDOMElement = document.querySelector('.my-query-class') as HTMLElement;
}
onClick() {
myDOMElement = document.querySelector('.my-query-class') as HTMLElement;
if (myDOMElement !== undefined) {
doSomething();
}
}
Now, even though this works fine, I have a feeling I am not suppossed to solve my problems using document.querySelector()
. That's why I am looking for an alternative that Angular offers. I have stumbled across the ViewChild
decorator and tried to implement my feature using it:
@ViewChild('.my-query-class') myDOMElementRef?: ElementRef;
myDOMElement?: HTMLElement;
ngAfterInitView() {
myDOMElement = myDOMElementRef.nativeElement;
}
onClick() {
if (myDOMElement !== undefined) {
doSomething();
}
}
It seems that myDOMElement
is undefined though. Apparently I don't understand the correct way of using ViewChild. Can somebody explain?
CodePudding user response:
I'm not an angular expert but I have find out that this is a common problem.
View child seems that it works if you use an id.
I let you a code that it works :)
import { AfterViewInit, Component, ElementRef, ViewChild } from '@angular/core';
@Component({
selector: 'app-question4',
template: `
<p #idElem >question4 works!</p>
<button (click)="onButtonClick()">Button</button>
`,
styleUrls: ['./question4.component.sass']
})
export class Question4Component implements AfterViewInit {
myDOMelement?: HTMLElement;
constructor() { }
// @ViewChild('.my-query-class') myDOMElementRef?: ElementRef;
@ViewChild('idElem') myDOMElementRef?:ElementRef;
ngAfterViewInit() {
this.myDOMelement = document.querySelector('.my-query-class') as HTMLElement;
console.log("this.myDOMElementRef");
console.log(this.myDOMelement);
console.log(this.myDOMElementRef);
}
onButtonClick(): void {
console.log("button clicked!!");
console.log(this.myDOMelement);
console.log(this.myDOMElementRef);
}
}
CodePudding user response:
If you are accessing an element in Angular using ViewChild, you have to give a template reference to that element.
<div #queryElem ></div>
In TS File
ViewChild('queryElem', {static: false}) divElem: ElementRef;
Also don't access element in ngOnInit hook. Always access DOMElement in ngAfterViewInit.
Refer this doc link to learn about hooks