Условный дубликат шаблона ссылки в нг-контенте с селектором

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

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 ответ

Решение

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

Представления могут быть двух типов View и 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);

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

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

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

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

Другие вопросы по тегам