Условный дубликат шаблона ссылки в нг-контенте с селектором
У меня есть компонент, который переключает шаблон компонента в зависимости от размера клиентского устройства. Код компонента:
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 для того же элемента: