1

I have a component which toggles the component's template based on client device size. Component code is:

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;
        });
    }    
}

I use it like this:

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

In the mobile size, everything works correctly but in desktop size the value passed to search(value) function is always an empty string.

When I debug the app, it seems that #searchInput templateref is not working correctly (value of the element it refers to is always empty).

Why templateref doesn't work correctly?

4

1 回答 1

7

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

视图可以是两种类型ViewEmbeddedViewng-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 编译器解析这个模板时,它会为每个视图创建一个带有refNodeIndices属性的ViewBuilder

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

包含当前模板中的所有引用。

让我们重现您的案例: 在此处输入图像描述

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

结果 Angular 处理同一元素上的点击事件:

在此处输入图像描述

于 2018-04-28T20:37:48.337 回答