Условный дубликат шаблона ссылки в нг-контенте с селектором - PullRequest
0 голосов
/ 28 апреля 2018

У меня есть компонент, который переключает шаблон компонента в зависимости от размера клиентского устройства. Код компонента:

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 работает неправильно?

1 Ответ

0 голосов
/ 28 апреля 2018

В угловых шаблонах эталонные переменные должны быть уникальными для каждого вида.

Представления могут быть двух типов Вид и EmbeddedView . Шаблоны, которые мы пишем в структурных директивах (внутри тега ng-template или *ngFor), представляют собой встроенные представления. Таким образом, мы можем иметь одно и то же имя переменной ссылки на шаблон в разных ng-шаблонах.

Пример см.

Давайте представим, что у нас есть 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 compiler анализирует этот шаблон, он создает по одному ViewBuilder на представление с refNodeIndices свойством:

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

, который содержит все ссылки в текущем шаблоне.

Давайте воспроизведем ваш случай: enter image description here

Мы видим, что вторая ссылочная переменная шаблона переопределяет предыдущую.

И в результате Angular обрабатывает событие клика для того же элемента:

enter image description here

...