#angular #typescript
#angular #typescript
Вопрос:
У меня есть родительский компонент, у которого есть title
поле. Это поле передается дочернему компоненту с помощью @input
декоратора. В моем дочернем компоненте я добавил некоторую логику для манипулирования title
значением, прежде чем показывать его в моем HTML.
Поскольку моя логика находится в ngInit
цепочке дочернего компонента, только в первый раз title
поле отражается правильно. Изменения, которые происходят с тех пор, не отражаются. Теперь я знаю, что это потому ngInit
, что вызывается один раз, но как мне инициировать изменение от моего родителя к дочернему элементу, сообщив ему перепроверить значение?
РЕДАКТИРОВАТЬ Добавлен фрагмент кода
Компонент заголовка (дочерний)
export class HeaderComponent implements OnInit {
@Input() title: string | Array<any>;
titleType = 'string';
tabletTitle: string | Array<any>;
constructor() { }
ngOnInit() {
if ( typeof this.title == 'object' ) {
this.titleType = 'array';
// For tablet - only send the last most array item
this.tabletTitle = [this.title[this.title.length - 1]]; // Has to be in the form of array (to be consistent with other orange header data type)
} else {
// Title is string - same for tablet
this.tabletTitle = this.title;
}
// Temporary to show filter button on catalog page
if ( this.page == 'catalog' ) {
this.showFilterButton = true;
}
}
}
Шаблон заголовка
<h1 *ngIf="titleType=='string'">{{title}}</h1>
<h1 *ngIf="titleType=='array'">
<ul class="header-breadcrumb">
<template ngFor let-item [ngForOf]="title | keyValueObject">
<li title="{{item.value['title']}}">
<a *ngIf="item.value['link']" [routerLink]="item.value['link']">{{item.value['title']}}</a>
<span *ngIf="!item.value['link']">{{item.value['title']}}</span>
</li>
<li *ngIf="!last" class="separator"></li>
</template>
</ul>
<ul class="header-breadcrumb tablet">
<li *ngFor="let item of tabletTitle | keyValueObject">
<a *ngIf="item.value['link']" [routerLink]="item.value['link']">{{item.value['title']}}</a>
<span *ngIf="!item.value['link']">{{item.value['title']}}</span>
</li>
</ul>
</h1>
Родительский компонент
if ( this.parentCatId ) {
// Push Parent Category name in header title
this.headerTitle.push({title: 'Parent'});
}
if ( this.subCatId ) {
// Push Sub Category name in header title
this.headerTitle.push({title: 'Child'});
}
Родительский компонент HTML
<app-header [title]="headerTitle"></app-header>
Комментарии:
1. Предоставьте некоторый фрагмент кода или создайте plunker / jsfiddle.
Ответ №1:
Вы можете либо создать @Input() title: string | Array<any>
сеттер, либо использовать ngOnChanges()
вместо ngOnInit()
. ngOnChanges()
вызывается каждый раз @Input()
при обновлении.
@Input() set title(value: string | Array<any>) {
...
}
или
ngOnChanges() {
if ( typeof this.title == 'object' ) {
this.titleType = 'array';
// For tablet - only send the last most array item
this.tabletTitle = [this.title[this.title.length - 1]]; // Has to be in the form of array (to be consistent with other orange header data type)
} else {
// Title is string - same for tablet
this.tabletTitle = this.title;
}
// Temporary to show filter button on catalog page
if ( this.page == 'catalog' ) {
this.showFilterButton = true;
}
}
Комментарии:
1. Спасибо за ваш быстрый ответ. Оказывает ли установка
@Input
asset
какое-либо влияние на производительность или оба метода работают одинаково? 🙂2. Нет, использование его в качестве установщика не оказывает никакого влияния на производительность. Установщик вызывается только один раз каждый раз, когда обнаружение изменений распознает изменение в родительском
headerTitle
свойстве.3. По какой-то сумасшедшей причине моя среда IDE (Sublime text 3) не распознает
@Input set
синтаксис. Помечает его красным:(4. Извините, понятия не имею о TS с Sublime 3
5. Ну, я использовал этот
ngOnChanges
метод и его обнаружение изменений. Однако по какой-то странной причине он не перерисовывает его в слое представления (DOM), какие-либо подсказки, почему это может быть?