elzoy
elzoy

Reputation: 5435

Access nested content children

@Directive({
  selector: '[some-directive]'
})
export class SomeDirective...
@Component({
  selector: 'inner-component',
  template: `
    <div some-directive></div>
  `
})
export class InnerComponent {
}
@Component({
  template: `
    <inner-component></inner-component>
  `
})
export class OuterComponent {
  @ContentChildren(SomeDirective, {descendants: true}) elementsWithDirective: QueryList<SomeDirective>;
}

Is this a proper way to get those directives? elementsWithDirective returns empty results array. I can't access it this way. The only way I can rid of the problem is to place the <div app-some-directive></div> directly inside OuterComponent's view but I want to avoid it.

Upvotes: 2

Views: 1501

Answers (2)

Michal
Michal

Reputation: 131

AFAIK currently there is no way to directly get grandchild elements from component. I don't know what is your use case, but you could:

  1. Add @ViewChild(InnerComponent) innerComponent: InnerComponent to your outer component
  2. Add @ViewChild(SomeDirective) someDirective: SomeDirective to your inner component
  3. from outer component access your directive through inner component in ngAfterViewInit ngAfterViewInit(): void { console.log(this.innerComponent.someDirective); }

stackblitz here

Upvotes: 3

ABOS
ABOS

Reputation: 3823

It seems you are confused with contentChildren and viewChildren. In your case, you should use viewChildren to query SomeDirective in InnerComponent, and emit results up to OuterComponent, e.g.

@Component({
  selector: 'outer-component',
  template: `    <inner-component 
    (elementsWithDirectiveChanges)="elementsWithDirectiveChanged($event)"> 
    </inner- 
    component>`
})
export class OuterComponent {
  elementsWithDirectiveChanged(change: any) {
    console.log(change);
  }
}

@Component({
  selector: 'inner-component',
  template: `
    <div some-directive>inner</div>
  `
})
export class InnerComponent {
  @ViewChildren(SomeDirective) elementsWithDirective!: QueryList<SomeDirective>;
  @Output() elementsWithDirectiveChanges = new EventEmitter();

  ngAfterViewInit() {
    this.elementsWithDirectiveChanges.emit(this.elementsWithDirective);
  }
}

demo https://stackblitz.com/edit/angular-2oesig?file=src%2Fapp%2Fhello.component.ts

Upvotes: 1

Related Questions