angular 2 access ng-content within component

46,351

Solution 1

You need to leverage the @ContentChild decorator for this.

@Component({
  selector: 'upper',
  template: `<ng-content></ng-content>`
})
export class UpperComponent {
  @Input 
  content: String;

  @ContentChild(...)
  element: any;
}

Edit

I investigated a bit more your issue and it's not possible to use @ContentChild here since you don't have a root inner DOM element.

You need to leverage the DOM directly. Here is a working solution:

@Component({
  selector: 'upper',
  template: `<ng-content></ng-content>`
})
export class UpperComponent {
  constructor(private elt:ElementRef, private renderer:Renderer) {
  }

  ngAfterViewInit() {
    var textNode = this.elt.nativeElement.childNodes[0];
    var textInput = textNode.nodeValue;
    this.renderer.setText(textNode, textInput.toUpperCase());
  }
}

See this plunkr for more details: https://plnkr.co/edit/KBxWOnyvLovboGWDGfat?p=preview

Solution 2

If you want to get a reference to a component of the transcluded content, you can use:

@Component({
    selector: 'upper',
    template: `<ng-content></ng-content>`
})
export class UpperComponent {
    @ContentChild(SomeComponent) content: SomeComponent;
}

If you wrap <ng-content> then you can access access to the transcluded content like

@Component({
    selector: 'upper',
    template: `
  <div #contentWrapper>
    <ng-content></ng-content>
  </div>`
})
export class UpperComponent {
    @ViewChild('contentWrapper') content: ElementRef;

    ngAfterViewInit() {
      console.debug(this.content.nativeElement);
    }
}

Solution 3

Good morning,

I've been doing a little research on this topic because something similar has happened to me in my project. What I have discovered is that there are two decorators that can help you for this solution: ViewChildren and ContentChildren. The difference mainly according to what I have found in the network is that ViewChildren accesses the interior of the component and ContentChildren accesses the DOM or the component itself.

To access the upper element from the ng-content you must change the upper element leaving it like this:

<upper #upper>my text to transform to upper case</upper>

And then simply to access the interior (In the component that has the ng-content):

  @ViewChildren('upper') upper: QueryList<ElementRef>

And to access the component in general (In the component that has the ng-content):

  @ContentChildren('upper') upper: QueryList<ElementRef>

Where did you get the information from: https://netbasal.com/understanding-viewchildren-contentchildren-and-querylist-in-angular-896b0c689f6e

Solution 4

https://angular.io/api/core/ContentChildren

class SomeDir implements AfterContentInit {

  @ContentChildren(ChildDirective) contentChildren : QueryList<ChildDirective>;

  ngAfterContentInit() {
    // contentChildren is set
  }
}

Note that if you do console.log(contentChildren), it will only work on ngAfterContentInit or a later event.

Share:
46,351

Related videos on Youtube

Daniel Kobler
Author by

Daniel Kobler

Updated on July 09, 2022

Comments

  • Daniel Kobler
    Daniel Kobler almost 2 years

    How can I access the "content" of a component from within the component class itself?

    I would like to do something like this:

    <upper>my text to transform to upper case</upper>
    

    How can I get the content or the upper tag within my component like I would use @Input for attributes?

    @Component({
        selector: 'upper',
        template: `<ng-content></ng-content>`
    })
    export class UpperComponent {
        @Input 
        content: String;
    }
    

    PS: I know I could use pipes for the upper case transformation, this is only an example, I don't want to create an upper component, just know how to access the component's content from with the component class.

    • Günter Zöchbauer
      Günter Zöchbauer about 8 years
      Do you want the HTML string or a reference to a specific component, ...?
  • Daniel Kobler
    Daniel Kobler about 8 years
    If I wrap it I should access it using \@ViewChild, not \@ContentChild ?
  • ykadaru
    ykadaru about 5 years
    What if the content being transcluded isn't an another component? What if you just want all the transcluded content within ng-content?
  • K-Dawg
    K-Dawg almost 3 years
    Very weird I'm doing exactly this even with forwardref and descendants: true, checking in the AfterContentInit() and it still comes back as an empty list.