Доступ к родительским @Компонент и vars из * Маршрутизированный * Детский компонент
Я пытаюсь переключить навигационное меню, расположенное в верхней части моего основного шаблона приложения, используя кнопку во вложенном дочернем компоненте. Я не могу понять, как добраться до компонента sidenav в родительском, чтобы сообщить ему sidenav.open()
.
Я знаю о @Input и @Output для дочернего компонента, но, насколько я понимаю, для использования этого мне нужно иметь какой-то тэг DOM для дочернего компонента, к которому они присоединяются? Например:
<app>
<sidenav-component #sidenav>...</sidenav-component>
<child [someInput]="some_parent_var" (childOpensNav)="sidenav.open()"></child>
</app>
Тонны статей о том, как это сделать. Проблема в том, что я направляюсь к этому компоненту, поэтому тег <child>
не существует явно в коде. Скорее мой код выглядит так:
<app>
<sidenav-component #sidenav>...</sidenav-component>
<router-outlet></router-outlet>
</app>
Если у меня есть дочерний компонент, который перенаправляется, как я могу сделать sidenav.open()
или каким-то образом получить доступ к компоненту родителя от дочернего?
Некоторые мысли: я провел некоторое исследование и подумал о нескольких подходах и не уверен, что они верны или даже будут работать... Один подход заключается в использовании услуги Injector и попытке перейти к родительскому, но это кажется неправильным:
// child component
constructor(injector: Injector) {
this.something = injector.parent.get(Something);
}
Или, возможно, создание службы в родительском объекте, как-то привязанное к компоненту Sidenav, а затем вставляя эту службу в дочерний элемент??
Ответы
Ответ 1
Самый простой и чистый способ - действительно использовать сервис.
Служба, как она может выглядеть:
export class DomService {
sidebarVisible: boolean = true;
showSidebar() {
sidebarVisible = true;
}
hideSidebar() {
sidebarVisible = false;
}
toggleSidebar() {
sidebarVisible = !sidebarVisible;
}
}
В своем вызове bootstrap
добавьте службу в список поставщиков:
bootstrap(App, [
// other providers
DomService
]);
В компонентах (возможно, в app.ts
, но также в вашем sidenav.ts
), где вы хотите показать/скрыть боковую панель, добавьте службу для инъекции:
constructor(private _domService: DomService) {
}
В вашем шаблоне, где вы хотите переключить/показать/скрыть, вы можете сделать это сейчас:
<sidenav-component *ngIf="_domService.sidebarVisible">...</sidenav-component>
<div id="toggle-sidebar" (click)="_domService.toggleSidebar()">toggle</div>
Ответ 2
Мне нравится принятый ответ, кажется более надежным способом Angular сделать это правильно (особенно если вы собираетесь добавлять дополнительные параметры).
Однако мне нужен быстрый грязный доступ к глобальному элементу по идентификатору. Все говорят об использовании @ViewChild, но я хочу идти по дереву. Я только что вернулся в школу и использовал это в методе компонентов:
document.getElementById('nav-panel').className = 'hide';
Если мы хотим, чтобы несколько копий этого работали (например, левое и правое меню), нам нужно что-то вводить детям, чтобы они знали, для какого идентификатора искать.