Обновить свойство родительского компонента из дочернего компонента в Angular 2
Я использую @input
для получения свойства из родительского компонента, чтобы активировать класс CSS в одном из элементов дочернего компонента.
Я могу получить свойство от родителя, а также активировать класс. Но это работает только один раз. Свойство, которое я получаю от родителя, - это логические данные, набранные, и когда я устанавливаю его статус false
из дочернего компонента, он не изменяется в родительском.
Plunkr: https://plnkr.co/edit/58xuZ1uzvToPhPtOING2?p=preview
app.ts
import {Component, NgModule} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
import { HeaderComponent } from './header';
import { SearchComponent } from './header/search';
@Component({
selector: 'my-app',
template: `
<app-header></app-header>
`,
})
export class App {
name:string;
constructor() {
}
}
@NgModule({
imports: [ BrowserModule ],
declarations: [ App, HeaderComponent, SearchComponent ],
bootstrap: [ App ]
})
export class AppModule {}
header.ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-header',
template: `<header>
<app-search [getSearchStatus]="isSearchActive"></app-search>
<button (click)="handleSearch()">Open Search</button>
</header>`
})
export class HeaderComponent implements OnInit {
isSearchActive = false;
handleSearch() {
this.isSearchActive = true
console.log(this.isSearchActive)
}
constructor() { }
ngOnInit() { }
}
заголовок /search.ts
import { Component, OnInit, Input } from '@angular/core';
@Component({
selector: 'app-search',
template: `<div id="search" [class.toggled]="getSearchStatus">
search
<button (click)="getSearchStatus = false" class="close">Close Search</button>
</div>`
})
export class SearchComponent implements OnInit {
@Input() getSearchStatus: boolean;
constructor() { }
ngOnInit() {
}
}
Пожалуйста, проверьте вышеуказанный плункер. Функция открытого поиска работает только один раз. После закрытия поиска он не запускается снова.
Является ли @input
подходящим вариантом использования для этого сценария? Пожалуйста, помогите мне исправить это. (Пожалуйста, обновите плункер).
Ответы
Ответ 1
Вам нужно использовать двустороннюю привязку данных.
@Input()
является одним из способов привязки данных.
для включения двухсторонней привязки данных вам нужно добавить @Output()
, соответствующий свойству, с суффиксом "Изменить"
@Input() getSearchStatus: boolean;
@Output() getSearchStatusChange = new EventEmitter<boolean>();
когда вы хотите опубликовать изменение, внесенное в ваше свойство родительскому объекту, вам необходимо уведомить родителя:
this.getSearchStatusChange.emit(newValue)
а в родителе вам нужно использовать обозначение banana-in-a-box для этого свойства:
[(getSearchStatus)]="myBoundProperty"
вы также можете привязать свойство и вызвать обратный вызов, когда он изменится в дочернем:
[getSearchStatus]="myBoundProperty" (getSearchStatusChange)="myCrazyCallback($event)"
см. plnkr
Ответ 2
Немного изменил ваш код, он работает и выглядит проще imo. Скажите, если вам это нравится.
https://plnkr.co/edit/oJOjEZfAfx8iKZmzB3NY?p=preview
Ответ 3
Еще один способ. Plunkr. То, что мы хотим, является единственным источником истины. На этот раз мы можем положить это на ребенка.
- Init в дочернем элементе:
searchStatus = false
- В родительском шаблоне получите экземпляр дочернего типа как
#as
или другое имя.
- Измените searchStatus в родителе с помощью
#as.searchStatus
и в дочернем this.searchStatus
.
Ответ 4
Другой подход: используйте rxjs/BehaviorSubject для передачи статуса между различными компонентами.
Здесь plunkr.
Я называю тему суффиксом "Rxx", поэтому BehaviorSubject для searchStatus будет searchStatusRxx.
- инициализировать его в родительском компоненте, например
searchStatusRxx = new BehaviorSubject(false);
,
- передать его дочернему компоненту с помощью @Input
- в дочернем шаблоне, вы выполняете асинхронный канал.
- как для родителя, так и для ребенка, вы меняете
searchStatusRxx.next(value)
, чтобы изменить последнее значение.