带有选择器的 ng-content 中的条件重复模板引用
Conditional duplicate templateref in ng-content with selector
我有一个组件可以根据客户端设备的大小切换组件的模板。组件代码为:
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 中,每个视图的模板引用变量应该是唯一的。
视图可以是两种类型 View 和 EmbeddedView。我们在结构指令中(在 ng-template
标记或 *ngFor
内)编写的模板表示嵌入式视图。这样我们就可以在不同的 ng-templates 中使用相同名称的模板引用变量。
示例见
- Dynamic template reference variable inside ngFor (Angular 2)
假设我们有 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 per view with refNodeIndices 属性:
private refNodeIndices: {[refName: string]: number} = Object.create(null);
包含当前模板中的所有引用。
让我们重现您的案例:
我们可以看到第二个模板引用变量覆盖了之前的变量。
结果 Angular 处理同一元素上的点击事件:
我有一个组件可以根据客户端设备的大小切换组件的模板。组件代码为:
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 中,每个视图的模板引用变量应该是唯一的。
视图可以是两种类型 View 和 EmbeddedView。我们在结构指令中(在 ng-template
标记或 *ngFor
内)编写的模板表示嵌入式视图。这样我们就可以在不同的 ng-templates 中使用相同名称的模板引用变量。
示例见
- Dynamic template reference variable inside ngFor (Angular 2)
假设我们有 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 per view with refNodeIndices 属性:
private refNodeIndices: {[refName: string]: number} = Object.create(null);
包含当前模板中的所有引用。
让我们重现您的案例:
我们可以看到第二个模板引用变量覆盖了之前的变量。
结果 Angular 处理同一元素上的点击事件: