Вопрос или проблема
У меня есть следующий шаблон:
<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
, вы можете воспользоваться следующими шагами.
-
Создание директивы с
exportAs
:
Убедитесь, что ваша директиваDrawerTrackDirective
имеет свойствоexportAs
. Это позволит вам ссылаться на неё в шаблоне.@Directive({ selector: '[drawer-track]', exportAs: 'drawerTrack' }) export class DrawerTrackDirective { constructor(public elementRef: ElementRef, @Optional() public scList: ScListComponent) {} }
-
Использование директивы и экспорт переменной:
В шаблоне, где вы используетеsc-list
, необходимо создать переменную ссылки с использованием#list="drawerTrack"
для её экспорта.<sc-list #list="drawerTrack" drawer-track></sc-list> <sc-drawer [drawerTrack]="list"></sc-drawer>
Здесь вы указываете, что
#list
будет экземпляром директивыdrawerTrack
. -
Получение доступа к элементу в
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 } } }
-
Использование
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
.