Angular 2+ directive - how to get nativeElement from child directive in the same or nested template

50 views Asked by At

I'm attempting to create a directive to manage ARIA Web accessible tab events using Angular 2+, but I'm having an issue with Angular Directives.

I want to have hierarchical directives so I can specify the parent and have access to child directives so I can bind the tabindex correctly.

I have a full example on stackblitz if you need to refer to that.

As an example I have 3 directives. AriaListBox, AriaLabel & AriaListItem. AriaListBox is the parent containing an AriaLabel and a collection of AriaListItems.

I have been able to get a reference to the AriaLabel using @ContentChild but cannot do the same with @ContentChildren to get references for the AriaListItem directive.

From the AriaListBox I'm attempting to use the following which I believe should be set in the ngAfterContentInit event following the Angular Documentation.

@ContentChildren(Directive, { descendants: true }) public items: QueryList<Directive>;

AriaListBox

src/aria/aria-listbox.directive.ts

@Directive({
  selector: '[AriaListBox]',
})
export class AriaListBoxDirective implements OnInit, AfterContentInit {
  @ContentChild(AriaLabelDirective) public label: AriaLabelDirective;
  @ContentChildren(AriaListItemDirective, { descendants: true })
  public listItems: QueryList<AriaListItemDirective>;

  constructor(private el: ElementRef, private searchService: SearchService) {}

  public ngAfterContentInit(): void {
    console.log('listItems', this.listItems);
  }
}

AriaLabel

src/aria/aria-label.directive.ts

@Directive({
  selector: '[AriaLabel]',
})
export class AriaLabelDirective {
  constructor(public el: ElementRef) {}
}

AriaListItem

src/aria/aria-listitem.directive.ts

@Directive({
  selector: '[AriaListItem]',
})
export class AriaListItemDirective {
  constructor(public el: ElementRef) {}
}

HTML

src/search-link-list/search-link-list.component.html

My HTML template uses the directives with the following.

<div AriaListBox>
  <h3 AriaLabel>{{ title$ | async }}</h3>
  <ul>
    <li *ngFor="let item of items$ | async">
      <a href="{{ item.url }}" #link AriaListItem>{{ item.name }}</a>
    </li>
  </ul>
</div>

Is there anything I have missed? I have attempted to get a reference using a selector @ContentChildren('AriaListItem') or the same with @ViewChildren(AriaListItemDirective) and similarly @ViewChildren('AriaListItem') But since it's a directive and not a component it also doesn't work.

The items$ are mocked inside the search.service.ts file and are rendered to the screen without any issue.

Edit --

If I inspect the LinkListItemComponent and the ListBoxDirective lifecycle events, I can see that the #link QueryList exists in the SearchLinkListComponent::ngAfterContentInit before the AriaListBoxDirective::ngAfterContentInit, so it seems that the Directive should have access to the content.

Thanks for any help!

0

There are 0 answers