search

Home  >  Q&A  >  body text

The root of an IntersectionObserver using getElementById is always null

In an Angular project, I want to limit the viewport of an IntersectionObserver to a specific part of the DOM.

I use id to define the element to be used as root:

<div id="container">
  <div class="page-list">
    <infinite-scroll-page (scrolled)="onInfiniteScroll()">
      ...
    </infinite-scroll-page>
  </div>
</div>

In the corresponding component, I use getElementById to define the root:

export class InfiniteScrollPageComponent implements OnDestroy {
  @Input() options: {root, threshold: number} = {root: document.getElementById('container'), threshold: 1};

  @ViewChild(AnchorDirectivePage, {read: ElementRef, static: false}) anchor: ElementRef<HTMLElement>;

  private observer: IntersectionObserver;

  constructor(private host: ElementRef) { }

  get element() {
    return this.host.nativeElement;
  }

  ngAfterViewInit() {
      const options = {
        root: document.getElementById('container'),
        ...this.options
      };

      console.log("options: ", JSON.stringify(options));
      //...

But the logged in root is always null.

What did i do wrong?

P粉501683874P粉501683874275 days ago422

reply all(1)I'll reply

  • P粉071602406

    P粉0716024062024-03-29 16:31:45

    First of all, your spread operator is the wrong way, so unfortunately you are overwriting your root right after using the default value set in @Input() Assignment (as far as I know, this isn't actually used as input?).

    Solving this problem may just require reversing the situation:

    const options = {
      root: document.getElementById('container'),
      ...this.options
    };

    should be

    const options = {
      ...this.options,
      root: document.getElementById('container')
    };

    Secondly, I'm wondering if it would make more sense to use @ViewChild and pass the reference to the container element from the parent to the InfiniteScrollPageComponent.

    parent.component.html

    ...

    parent.component.ts

    export class ParentComponent {
      @ViewChild('Container') containerRef: ElementRef;
    }

    infinite-page-component.component.ts

    export class InfiniteScrollPageComponent {
      @Input() containerRef: ElementRef;
    
      ngAfterViewInit() {
        const options = {
          ...this.options
          root: containerRef.nativeElement,
        };
      }

    reply
    0
  • Cancelreply