fortuneNext
fortuneNext

Reputation: 129

How can I access an already transcluded ContentChild?

I have a angular component app-b that is used within a component app-a that is used in the app-component. The app-component has some content in app-a, app-a transcludes this with ng-content into app-b, app-b shows it with another ng-content - but how can I access this content within the component (and not it's template)?

I would think that ContentChild is the correct approach but appears to be wrong.

Example:

https://stackblitz.com/edit/angular-ddldwi

EDIT: Updated example

Upvotes: 1

Views: 901

Answers (3)

lorinpa
lorinpa

Reputation: 556

I recommend sharing the data between components. For example, move your data (E.G. dummyName) into a service. Then add the service to each component (where you need the shared data).

Service:

import { Injectable } from '@angular/core';

@Injectable()
export class DataShareService {
   public dummyName: String = 'one';
   constructor() { }
}

Add the new service to app.module.ts:

providers: [DataShareService],

Child Component:

import { DataShareService } from './data-share.service';
import { Component } from '@angular/core';

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html'
})
export class ChildComponent  {
  constructor(public ds: DataShareService) { }

  toggle() {
    this.ds.dummyName = this.ds.dummyName === 'one' ? 'two' : 'one';
  }
}

Child Component template (html):

<p> {{ds.dummyName}}</p>
<button (click)="toggle()">Click Me to Toggle Value</button>

Parent Component:

import { Component, OnInit } from '@angular/core';
import { DataShareService } from './data-share.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html'
})
export class AppComponent  {
  constructor(public ds: DataShareService) {}

  displayNumber() {
   return this.ds.dummyName === 'one' ? 1 : 2;
  }
}

Parent Component template (html):

<p> this is the parent component:</p>
<div> value as string:   {{ ds.dummyName }} </div>
<div> value as number: <span [textContent]="displayNumber()"></span></div>
<hr>
<p> this is the child component:</p>
<app-child></app-child>

Note! The child component toggle() function demonstrates how you can change the data. The parent component displayNumber() function demonstrates how to use the data, independent of it's display (I.E. as just pure data).

Upvotes: 1

Tomasz Kula
Tomasz Kula

Reputation: 16837

You cannot query by tag name with @ContentChild decorator. You can query either by template variable, component or directive selector.

app-a.component.html

<app-b>
  <ng-content></ng-content>
  <p #myContent>This is a content child for app-b.</p>
</app-b>

app-b.component.ts

 import { Component, AfterContentInit, ContentChild } from '@angular/core';

@Component({
  selector: 'app-b',
  templateUrl: './b.component.html',
  styleUrls: ['./b.component.css']
})
export class BComponent implements AfterContentInit {
  @ContentChild('myContent') contentchild;

  ngAfterContentInit() {
    console.log(this.contentchild);
  }
}

Live demo

Upvotes: 1

Related Questions