2

I have a component that declares some outside html around an <ng-content> tag. However, if the content is of a specific component class, or if it contains certain tags, I'd like to be able to access those.

For example, in the code below, the component MyComponent has been set as the content of MyWrapper. From within MyWrapper, how can I get the MyComponent that has been stuck in it?

Example

--Wrapper Template--

...
<ng-content #content></ng-content>
...

--Wrapper Usage--

<my-wrapper>
  <my-component></my-component>
</my-wrapper>

My preference would be able to get an object representing the component that was set inside the ng-content, so I can access it using typescript. But, I'll settle for just being able to get DOM objects. Or, if I'm totally on the wrong track and should be doing this another way, I'll welcome that too.

theMayer
  • 15,456
  • 7
  • 58
  • 90
  • Possible duplicate of [angular 2 access ng-content within component](https://stackoverflow.com/questions/36545478/angular-2-access-ng-content-within-component) – Deblaton Jean-Philippe May 25 '18 at 16:06
  • So- a loose reading of my question is a duplicate of that... however, I think mine is clearer as to what I'm looking for, which would make the highly up-voted non-accepted answer on that one the correct answer for mine. – theMayer May 25 '18 at 16:23
  • I'd like a way to get the actual angular component *class*, not just the HTML, if that's possible. – theMayer May 25 '18 at 16:51
  • You're right, I retracted my close vote ;-) Anyway, the accepted answer is the key of your problem, the higly upvoted answer is not. – Deblaton Jean-Philippe May 25 '18 at 17:04
  • Have you considered `@ContentChild` ? – J. Pichardo May 25 '18 at 17:05

2 Answers2

3

After reading a bit, it appears that a slight adjustment to the code is necessary in the wrapper class to be able to access the DOM elements:

Instead of

...
<ng-content #content></ng-content>
...

As this answer on a different question indicates, one must wrap the ng-content in a div element. Then, use @ViewChild to access it, as follows:

--Template--

<div #content>
  <ng-content></ng-content>
</div>

--Class--

@ViewChild('content')
private content;

The content field will be available from within the AfterViewInit method in the wrapper component (but not necessarily before):

ngAfterViewInit() {
  if (this.content) {
    console.log('content was present');
  }
  if (this.content instanceof MyComponent) {
    console.log('this should work too, but it doesn't.');
  }
}

A shortfall of this is that I have not discovered a way to get back to the original component class.

theMayer
  • 15,456
  • 7
  • 58
  • 90
0

I dit this a while ago, and don't have a piece of code to demonstrate it, so I hope I remember it correctly

in your template, you will have to do the following :

<my-wrapper>
  <my-component #mySubComponent></my-component>  
</my-wrapper>

and in your MyWrapperComponent the following :

@ContentChild('mySubComponent')
private subComponent: MyComponent;

ngAfterContentInit() {
    // You have access here to your public properties and methods of your sub component
}
Deblaton Jean-Philippe
  • 11,188
  • 3
  • 49
  • 66