3

My app is structured like this:

<nav></nav>
<router-outlet></router-outlet>
<footer></footer>

In the router-outlet I have different components based on the route. In a few of those pages I need to access the DOM elements of either the nav or the footer for things like pageYOffset, height and etc. for sticky positioning. I know of things like ViewChild, Renderer2 and ElementRef but not really sure how it would work. Do I create a service? What might that look like?

1 Answer 1

4

Assuming that the child components are of type NavComponent and FooterComponent, you can retrieve the corresponding DOM elements with @ViewChild(..., { read: ElementRef }) in ngAfterViewInit:

@ViewChild(NavComponent, { read: ElementRef }) private navElementRef: ElementRef;
@ViewChild(FooterComponent, { read: ElementRef }) private footerElementRef: ElementRef;

ngAfterViewInit() {
  const navElement = this.navElementRef.nativeElement;
  const footerElement = this.footerElementRef.nativeElement;
  ...
}

See this stackblitz for a demo.


These elements can be made accessible to other parts of the application with a simple service:

export class AppElementsService {
  public navElement: HTMLElement;
  public footerElement: HTMLElement;
}

and set in the application component:

@ViewChild(NavComponent, { read: ElementRef }) private navElementRef: ElementRef;
@ViewChild(FooterComponent, { read: ElementRef }) private footerElementRef: ElementRef;

constructor(private appElementsService: AppElementService) { }

ngAfterViewInit() {
  this.appElementsService.navElement = this.navElementRef.nativeElement;
  this.appElementsService.footerElement = this.footerElementRef.nativeElement;
}

Note: you may need to set the display style attribute of the nav and footer components to block or inline-block in order to get the position and size of the corresponding elements.

Not the answer you're looking for? Browse other questions tagged or ask your own question.