0

Ultimately I want to use the getBoundingClientRect() method to detect the bottom of my component and am using the @ViewChild directive to do so. Normally in the past when doing this we need to access the nativeElement of the element we target with the @ViewChild however it doesn't seem to work on components.

As of right now I'm doing it this way which works

template

<section #intro>
    <intro />
</section>

component

export class HomePageComponent implements AfterViewInit {

  @ViewChild('intro', {static: true}) Intro?: ElementRef;
  
  // irrelevant code

  private detectIntroHeight():number{
    return this.Intro?.nativeElement.getBoundingClientRect().bottom;
  }
}

This code works. However if I do this

template

<intro #intro />

component

export class HomePageComponent implements AfterViewInit {

  @ViewChild('intro', {static: true}) Intro?: IntroComponent;
  
  // irrelevant code

  private detectIntroHeight():number{
    return this.Intro?.nativeElement.getBoundingClientRect().bottom;
  }
}

I get an error saying nativeElement doesn't exist on IntroComponent. I've tried making it of type ElementRef<IntroComponent> and got the same error. I also removed nativeElement just leaving the getBoundingClientRect() method and got the same error saying it doesn't exist on IntroComponent.

Is there a way to make that work directly on my component without having to wrap it in an HTML element? I'd rather not have to wrap it just so I can detect where its located on the page.

Here's a basic stackblitz that demonstrates this issue.

Optiq
  • 2,835
  • 4
  • 33
  • 68
  • What is Intro markup? How the component is defined. probably it is not a dom element, while section is and can be accessed with nativelement and it has height, etc – Vega Jul 08 '23 at 07:39
  • I think, reading it's ElementRef should work. See ViewChild docs. – derstauner Jul 08 '23 at 09:08
  • when I do `ElementRef` without the `` reference I get an error saying `Cannot read properties of undefined (reading 'getBoundingClientRect')`. – Optiq Jul 08 '23 at 18:37
  • 1
    In the case of ``, you should try `@ViewChild('intro', {read: ElementRef}, {static: true}) introElement: ElementRef;` as explained in [this answer](https://stackoverflow.com/a/39909203/1009922). If it works, we could mark your question as a duplicate of [this one](https://stackoverflow.com/q/39908967/1009922). – ConnorsFan Jul 08 '23 at 23:22
  • 1
    THAT WORKS!!!! However instead of having `read` and `static` in two separate objects, I passed them in the same object as `{read: ElementRef, static: true}`. – Optiq Jul 09 '23 at 01:28

1 Answers1

0

Have you tried the same but with @ContentChild and make sure you don’t call the method before rendering is done?

ToneyPK
  • 21
  • 4
  • I just tried it according to what the documentation shows and not getting any results. When I `console.log()` the results I get `undefined`. However the example they give in the docs is on a `@Directive` rather than a component, how would I need to set it up? – Optiq Jul 08 '23 at 19:17
  • Can you try calling the method from ngAfterViewInit - any of the queries above. Is it still undefined? Please create a stackblitz and I will help you:) – ToneyPK Jul 08 '23 at 21:02
  • Yes even with `ngAfterViewInit` I get the same error. However when wrapped in an HTML element I don't have any issues. – Optiq Jul 08 '23 at 21:30
  • I just updated my post with a stackblitz. The problem occurs with both standalone components and ones imported into a module which I included in the demo. – Optiq Jul 08 '23 at 23:01