从角度2的子组件更新父组件属性

我使用 @input接收来自父组件的属性,以激活子组件元素中的一个 CSS 类。

我能够从父类接收属性并激活类。但这招只管用一次。我从父组件接收到的属性是一个布尔型数据类型,当我从子组件将其状态设置为 false时,它不会在父组件中改变。

普朗克: https://plnkr.co/edit/58xuZ1uzvToPhPtOING2?p=preview

应用程序

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 {}

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() { }
}

Header/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是这个场景的正确用例吗? 请帮助我解决这个问题。(请更新活塞)。

109845 次浏览

You need to use 2 way data-binding.

@Input() is one way data-binding. to enable 2 way data-binding you need to add an @Output() corresponding to the property, with a "Change" suffix

@Input() getSearchStatus: boolean;
@Output() getSearchStatusChange = new EventEmitter<boolean>();

when you want to publish the change made to your property to the parent, you need to notify the parent with:

this.getSearchStatusChange.emit(newValue)

and in the parent you need to use the banana-in-a-box notation for that property:

[(getSearchStatus)]="myBoundProperty"

you can also bind to the property and trigger a callback when it changes in child:

[getSearchStatus]="myBoundProperty" (getSearchStatusChange)="myCrazyCallback($event)"

see the plnkr

Edited your code a little bit, it works and looks simplier imo. Tell me if you like it.

https://plnkr.co/edit/oJOjEZfAfx8iKZmzB3NY?p=preview

Another approach: use rxjs/BehaviorSubject to pass status between different components.
Here's the plunkr.
I name subject with a suffix 'Rxx', so the BehaviorSubject for searchStatus will be searchStatusRxx.

  1. initialize it in parent component like searchStatusRxx = new BehaviorSubject(false);,
  2. pass it to child component using @Input
  3. in child template, you do async pipe.
  4. in both parent and child, you do searchStatusRxx.next(value) to change the latest value.

Yet another way. Plunkr. What we want is a single source of truth. We can put that in child this time.

  • Init in child: searchStatus = false
  • In parent template, get the instance of child as #as or whatever name.
  • Change searchStatus in parent using #as.searchStatus and in child this.searchStatus.