【问题标题】:How to access template reference variables from parent in a child?如何从孩子的父母访问模板引用变量?
【发布时间】:2018-04-07 01:41:48
【问题描述】:

我正试图分别了解 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 中传递这样的引用是“不”,我实际上应该使用基于事件的触发器或类似的东西?

【问题讨论】:

  • sidenav 变量到底指的是什么?你能告诉我们那个代码吗?

标签: angular


【解决方案1】:

这是正常的父/子组件通信。您可以这样做的方法是只在孩子上公开一个输出事件:

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,您可能只想解决所有情况的问题并使用可观察的共享服务:

side-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>

然后您可以将服务注入任意组件并根据需要使用它。

【讨论】:

  • 非常棒!感谢您提供这两种方法,因为我肯定迟早会同时使用它们! :)
  • 我可以问一个小问题:像(openNav) 这样的“参数”是什么?这是子视图的某种构造函数参数吗?为什么在第一个示例中是@Output 而不是@Input
  • (openNav) 是标准的角度输出事件绑定。子组件正在输出一个事件,而父组件通过该语法绑定到它。这是一个@Output,因为它是从子级生成的输出,而不是从父级传递给子级的输入。一个例子是您熟悉的 (click)="" 语法。 click 是一个 Angular 框架,提供来自原生 HTML 组件的输出事件,以便于绑定。
  • 啊,明白了。再次感谢! :)
  • 绝对精彩 非常感谢@bryan60 ...第二种方法绝对是一种。干杯
猜你喜欢
  • 2013-07-25
  • 1970-01-01
  • 1970-01-01
  • 2014-01-24
  • 2011-08-29
  • 2017-11-04
  • 2016-06-10
  • 1970-01-01
  • 2017-12-17
相关资源
最近更新 更多