我试图分别围绕Angular2和Typescript。我想要做的是从子组件中的按钮打开sidenav - 这里app-header
。
我知道我可以用
打开它<button mat-button (click)="sidenav.open()">Open sidenav</button>
但这只有在我将其放在父模板中时才会起作用,因为它引用模板变量引用sidenav
。但是,正如我所说,我想基于点击一个孩子的按钮打开它。
这将是我的布局/应用模板:
<mat-sidenav-container>
<mat-sidenav #sidenav>
<!-- sidenav content -->
Here comes the menu ..
</mat-sidenav>
<div>
<app-header>
<!-- Application header -->
</app-header>
</div>
</mat-sidenav-container>
这将是标题模板:
<div>
header for {{title}} works!
<button mat-button (click)="sidenav.open()">Open sidenav</button>
</div>
当然这会失败,因为我无法引用sidenav
- 所以如何正确地从孩子中访问sidenav
?
或者在Angular2中将这样的引用传递给“no no”,我实际上应该使用基于事件的触发器或类似的东西?
答案 0 :(得分:4)
这是正常的父/子组件通信。您可以这样做的方法是在子项上公开输出事件:
parent.component.html摘录:
<child-component (openNav)="sidenav.open()"></child-component>
并且在孩子中,您只需将按钮单击绑定以发出该事件:
child.component.ts:
@Output() openNav = new EventEmitter();
child.component.html:
<button (click)="openNav.emit()">Open Nav</button>
然而,因为这是一个可能需要在很多地方访问的sidenav,甚至可能在嵌套的地方,你可能只想解决所有情况下的问题并使用共享服务observable:
侧nav.service.ts:
@Injectable()
export class SideNavService {
private openNavSource = new Subject(); // never expose subjects directly
openNav$ = this.openNavSource.asObservable();
openNav = () => this.openNavSource.next();
}
适当地提供,并将其注入父母和子女以供使用
parent.component.ts:
@ViewChild('sidenav') sidenav; // get your template reference in the component
constructor(private sideNavService: SideNavService) { }
private sideNavSub;
ngOnInit() {
this.sideNavSub = this.sideNavService.openNav$.subscribe(() => this.sidenav.open());
}
ngOnDestroy() {
this.sideNavSub.unsubscribe(); //clean your subscriptions
}
child.component.ts:
constructor(private sideNavService: SideNavService) { }
openNav() {
this.sideNavService.openNav(); // looks repetitive but accessing injectd services in templates is bad practice and will cause pains down the line
}
child.component.html:
<button (click)="openNav()">Open Nav</button>
然后您可以将服务注入任意组件并根据需要使用它。