【问题标题】:Conditional duplicate templateref in ng-content with selector带有选择器的 ng-content 中的条件重复模板引用
【发布时间】:2018-10-08 23:30:10
【问题描述】:

我有一个组件可以根据客户端设备大小切换组件的模板。组件代码为:

import {Component} from '@angular/core';
import {BreakpointObserver, Breakpoints} from '@angular/cdk/layout';

@Component({
    selector: 'ui-switcher',
    template: `
        <ng-content *ngIf="isSmall" select="mobile"></ng-content>
        <ng-content *ngIf="!isSmall" select="web"></ng-content>
`
})
export class UiSwitcherComponent {
    public isSmall: boolean;

    constructor(breakpointObserver: BreakpointObserver) {
        breakpointObserver.observe([Breakpoints.Small, Breakpoints.XSmall]).subscribe(result => {
            this.isSmall = result.matches;
        });
    }    
}

我是这样使用的:

<ui-switcher>
    <web>
        <!-- some commented details -->
        <input class="form-control mr-2" #searchInput 
        type="text" (keyup)="this.search(searchInput.value)">
    </web>

    <mobile>
        <!-- some commented details -->
        <input class="form-control" #searchInput 
        type="text" (keyup)="this.search(searchInput.value)">
    </mobile>
</ui-switcher>

在移动设备大小中,一切正常,但在桌面大小中,传递给 search(value) 函数的值始终为空字符串。

当我调试应用程序时,#searchInput templateref 似乎无法正常工作(它所引用的元素的值始终为空)。

为什么 templateref 不能正常工作?

【问题讨论】:

  • 我不相信你可以有两个具有相同模板引用名称的元素,角度模板编译器将始终采用第一个元素并忽略第二个
  • 但现在似乎跳过了第一个,因为在移动设备中一切正常
  • 我不知道它应该如何表现,这充其量是无证行为......

标签: angular angular-template ng-content


【解决方案1】:

在角度模板中,每个视图的引用变量应该是唯一的。

View 可以是 ViewEmbeddedView 两种。我们在结构指令(在ng-template 标签或*ngFor)中编写的模板代表嵌入式视图。这样我们就可以在不同的 ng-templates 中拥有相同名称的模板引用变量。

示例见

假设我们有 AppComponent 并在模板中写道:

<ui-switcher>
    <web>
        <!-- some commented details -->
        <input class="form-control mr-2" #searchInput 
        type="text" (keyup)="this.search(searchInput.value)">
    </web>

    <mobile>
        <!-- some commented details -->
        <input class="form-control" #searchInput 
        type="text" (keyup)="this.search(searchInput.value)">
    </mobile>
</ui-switcher>

Angular 将其视为一个 AppComponentView,因为此模板中没有任何结构指令。两个输入属于同一个视图。

现在,当 Angular 编译器解析这个模板时,它会为每个视图创建一个 ViewBuilder,并带有 refNodeIndices 属性:

private refNodeIndices: {[refName: string]: number} = Object.create(null);

保存当前模板中的所有引用。

让我们重现您的案例:

我们可以看到第二个模板引用变量覆盖了前一个。

因此 Angular 会处理同一元素上的点击事件:

【讨论】:

  • 感谢您的详细解释。 ui-switcher 组件中有一个结构组件。有没有办法在 部分使用相同的模板引用?
  • 但是 不是组件,它们只是 ui-switcher 组件中 ng-content 的选择器
猜你喜欢
  • 1970-01-01
  • 2017-05-07
  • 2019-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-07
  • 2020-03-22
相关资源
最近更新 更多