Получение директивы компонента из другого компонента

Вопрос или проблема

У меня есть следующий шаблон:

<sc-list #list drawer-track> </sc-list>

<sc-drawer [drawerTrack]="list"></sc-drawer>

Мне нужно получить элемент хоста sc-list внутри компонента sc-drawer, используя директиву drawer-track.

Я пытался использовать Injector или EnvironmentInjector внутри компонента sc-drawer, но не смог понять, как это сделать, или, возможно, есть другой подход, о котором я не знаю.

При создании директивы вы можете указать “exportAs”

@Directive(
{
  selector: 'drawer-track',
  exportAs: 'drawerTrack'  //<-- эта строка
})export class DrawerTrackDirective {

}

Теперь, когда вы используете переменную ссылки на шаблон, вы можете указать, что ваша переменная должна быть этой директивой

<sc-list #list="drawerTrack" drawer-track> </sc-list>

(Это то же самое, например, когда вы используете ngModel и пишете #name="ngModel")

Теперь вы можете внедрить в вашу директиву drawerTrack elementRef (объявить как публичный) или sc-list (использовать Optional, если ваша директива применяется не только к sc-list)

constructor(public elementRef:ElementRef,
            @Optional() public scList:ScListComponent){}

Таким образом, вы можете использовать в .ts в вашем sc-drawer

console.log(this.drawerTrack.elementRef);
console.log(this.drawerTrack.scList.any-property);
//или выполнить функцию
this.drawerTrack.scList.any-function()

ПРИМЕЧАНИЕ: когда мы используем ViewChild, мы можем использовать {read:ClassName}, например:

@ViewChild('list',{read:DrawerTrackDirective})
                   listAsTrackDirective!:DrawerTrackDirective

А в .html

<sc-drawer [drawerTrack]="listAsTrackDirective"></sc-drawer>

Ответ или решение

Для получения хоста компонента sc-list внутри компонента sc-drawer с использованием директивы drawer-track, вы можете воспользоваться следующими шагами.

  1. Создание директивы с exportAs:
    Убедитесь, что ваша директива DrawerTrackDirective имеет свойство exportAs. Это позволит вам ссылаться на неё в шаблоне.

    @Directive({
     selector: '[drawer-track]',
     exportAs: 'drawerTrack'
    })
    export class DrawerTrackDirective {
     constructor(public elementRef: ElementRef,
                 @Optional() public scList: ScListComponent) {}
    }
  2. Использование директивы и экспорт переменной:
    В шаблоне, где вы используете sc-list, необходимо создать переменную ссылки с использованием #list="drawerTrack" для её экспорта.

    <sc-list #list="drawerTrack" drawer-track></sc-list>
    <sc-drawer [drawerTrack]="list"></sc-drawer>

    Здесь вы указываете, что #list будет экземпляром директивы drawerTrack.

  3. Получение доступа к элементу в sc-drawer:
    В вашем компоненте sc-drawer вы можете теперь получать доступ к ссылке на DrawerTrackDirective, переданную через входной параметр:

    @Component({
     selector: 'sc-drawer',
     templateUrl: './sc-drawer.component.html'
    })
    export class ScDrawerComponent {
     @Input() drawerTrack!: DrawerTrackDirective;
    
     ngOnInit() {
       if (this.drawerTrack) {
         console.log(this.drawerTrack.elementRef); // Здесь вы получаете элемент
         console.log(this.drawerTrack.scList?.anyProperty); // Доступ к свойству компонента sc-list
         this.drawerTrack.scList?.anyFunction(); // Вызов функции из sc-list
       }
     }
    }
  4. Использование ViewChild (опционально):
    Если вам нужно извлечь директиву непосредственно через ViewChild, вы можете сделать это следующим образом:

    @Component({
     selector: 'sc-drawer',
     templateUrl: './sc-drawer.component.html'
    })
    export class ScDrawerComponent {
     @ViewChild('list', { read: DrawerTrackDirective }) 
     listAsTrackDirective!: DrawerTrackDirective;
    
     ngOnInit() {
       console.log(this.listAsTrackDirective.elementRef);
       console.log(this.listAsTrackDirective.scList?.anyProperty);
       this.listAsTrackDirective.scList?.anyFunction();
     }
    }

    В этом случае вам нужно будет использовать переменную #list в вашем sc-drawer:

    <sc-list #list="drawerTrack" drawer-track></sc-list>
    <sc-drawer *ngIf="list" [drawerTrack]="list"></sc-drawer>

Таким образом, вы сможете получить доступ к элементу sc-list внутри компонента sc-drawer, а также использовать всю необходимую функциональность и свойства компонента, связанные с директивой drawer-track.

Оцените материал
Добавить комментарий

Капча загружается...