1

I have a my-alert-component which looks like this:

import { Component, OnInit,Input } from '@angular/core';

@Component({
  selector: 'app-my-alert',
  template: `
    <h1 (click)="alert()">{{type}}</h1>
    <ng-content></ng-content>
    `
})
export class MyAlertComponent implements OnInit {

  @Input() type: string = "Success";

  alert(){
    console.log("alert");
  }

  constructor() { }

  ngOnInit() {
  }

}

And in my app component, I am doing the following:

import { Component,ComponentRef,ComponentFactory,ViewContainerRef, ComponentFactoryResolver,ChangeDetectorRef, ViewChild, TemplateRef, ViewChildren, QueryList, AfterViewInit,ElementRef, ContentChild, AfterContentInit } from '@angular/core';
import { MyAlertComponent } from './my-alert.component';
@Component({
  selector: 'app-root',
  template: `
    <app-my-alert>
      <p #insideNgContentVar>A paragraph inside ng-content</p>
    </app-my-alert>
    <app-my-alert type="danger"></app-my-alert>
    <app-my-alert type="success"></app-my-alert>
  `
})
export class AppComponent implements AfterViewInit{
  @ViewChildren(MyAlertComponent) alertComponents : QueryList<AlertComponent>;
  @ContentChild('insideNgContentVar') insideNgContent:ElementRef;

  ngAfterContentInit(){
    console.log(this.insideNgContent.nativeElement.textContent);
  }

  ngAfterViewInit(){
    this.alertComponents.forEach((alertComponentInstance) => console.log(alertComponentInstance));
  }
}

This is pretty simple, I thought.

But the error I am getting is:

EXCEPTION: Error in :0:0 caused by: Cannot read property 'nativeElement' of undefined

What am I doing wrong?

EDIT

If in my-alert-component I do:

@Component({
  selector: 'app-my-alert',
  template: `
    <h1 (click)="alert()">{{type}}</h1>
    <ng-content></ng-content>
    `
})
export class MyAlertComponent implements AfterContentInit,AfterViewInit {

  @Input() type: string = "Success";

  @ContentChild('insideNgContent') insideNgContentRef:ElementRef;

  alert(){
    console.log("alert");
  }

  ngAfterContentInit(){
    console.log(this.insideNgContentRef.nativeElement.textContent);
  }

And in my app component:

template: `
    <app-my-alert>
    </app-my-alert>
    <app-my-alert type="danger">
        <p #insideNgContent>A paragraph inside ng-content</p>
    </app-my-alert>
    <app-my-alert type="success"></app-my-alert>
  `

After these changes also, something seems to be missing.

What is that?

StrugglingCoder
  • 4,781
  • 16
  • 69
  • 103

1 Answers1

-1

I think you should be using @ViewChild here, as per this answer:

https://stackoverflow.com/a/34327754/5018962

So basically, ViewChild is going to look for components in the DOM that are defined in your component's template, but ContentChild will look for components defined as ng-content of your app-root component itself, but not ng-content of some child components. But in this case no one is using your app-root component and no one is going to inject any DOM there, so that's why you get undefined

EDIT.

It would work, if you added the following line to the app-my-alert component:

@ContentChild('insideNgContentVar') insideNgContent:ElementRef;

because that means, look at what is defined in the ng-content of app-my-alert. Hope that sheds some light on this topic

eddyP23
  • 6,420
  • 7
  • 49
  • 87
  • But is not that wrong? I am accessing something from the projected content, and should not that be available in @ContentChild()? – StrugglingCoder Nov 22 '17 at 09:22
  • `@ViewChild()` works. But Still why does not `@ContentChild()'? See the update pls. I have tried your changes. They totally make sense. But still, why am I getting the same error? – StrugglingCoder Nov 22 '17 at 13:33
  • And as I tried to explained a few time. `@ViewChild` looks for stuff that you can literally see in the template of the component. `@ContentChild` is for stuff that you can't literally see in template, but will be injected as an `ng-component` when your component gets used – eddyP23 Nov 22 '17 at 13:54
  • Ok. But as I understood I can still use the `ContentChild()` in my alert component. That's what you also pointed also. So, even after that, in my edit, I am getting `Cannot read property 'nativeElement' of undefined`. – StrugglingCoder Nov 22 '17 at 15:00
  • It looks that it should work. I assume that you have seen this https://netbasal.com/understanding-viewchildren-contentchildren-and-querylist-in-angular-896b0c689f6e – eddyP23 Nov 22 '17 at 15:16
  • Yes. I was following the examples. But I could not get it work. So I am stuck :( – StrugglingCoder Nov 22 '17 at 15:28
  • If you provided more details like an error or something, that might help, because the syntax you provided looks alright. Also opening a new question might be a good idea, as now you have two separate questions mushed together – eddyP23 Nov 23 '17 at 10:14