在Angular 2中从子组件更新父组件属性


79

@input用来从父组件接收属性,以便在子组件的元素之一中激活CSS类。

我可以从父级接收属性,也可以激活该类。但这仅工作一次。我从父级收到的属性是一个布尔数据类型,当我将其状态设置为false子级组件时,它在父级中不会更改。

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

标头/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这种情况是否合适?请帮我解决这个问题。(请更新活塞)。


设置为truein后,您在哪里设置“ this.isSearchActive = false;” handleSearch()
君特Zöchbauer

在页眉/ search.ts '<按钮(点击)= “getSearchStatus =假”类= “接近”>'
车身

Answers:


135

您需要使用2种方式进行数据绑定。

@Input()是数据绑定的一种方式。要启用2种方式的数据绑定,您需要添加一个@Output()与属性相对应的后缀“ Change”

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

当您要将对属性所做的更改发布给父级时,需要通过以下方式通知父级:

this.getSearchStatusChange.emit(newValue)

并且在父级中,您需要对该属性使用“香蕉盒”表示法:

[(getSearchStatus)]="myBoundProperty"

您还可以绑定到该属性,并在其子项发生更改时触发回调:

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

plnkr


谢谢您的回复。你能给我更新一下吗?
身体

1
对于与使用相同的行为,这将增加额外的工作@Output()。这听起来像是重新装进轮子。@RobertVangor
n00dl3

2
使用ReactiveForms时,即使标记了child属性public,我也无法使用“香蕉盒”方法,并收到错误消息,指出它不是组件的已知属性(propertyChanged)="setParentProp($event)"
mc01

1
我无法回答您的问题,因为它应有自己的职位。您的问题是您在父母的变更检测周期之后立即发出变更。换句话说,您已经设法进行更改检测以触发一些Angular不允许的更改。@manoj
n00dl3

2
@Chandrakant不,要使用香蕉盒语法,您必须使用更改后缀。对于自定义输出,您可以根据需要命名。香蕉盒只是一个非常愚蠢的语法糖,很多人滥用了它
Allwe

7

另一种方法:使用rxjs / BehaviorSubject在不同组件之间传递状态。
这是小矮人
我用后缀“ Rxx”命名主题,所以searchStatus的BehaviorSubject将为searchStatusRxx。

  1. 在像父组件初始化searchStatusRxx = new BehaviorSubject(false);
  2. 使用@Input将其传递给子组件
  3. 在子模板中,您执行异步管道。
  4. 在父级和子级中,您searchStatusRxx.next(value)都要更改最新值。


2

还有另一种方式。Plunkr。我们想要的是真理的单一来源。这次我们可以把它放在孩子身上。

  • 在孩子中初始化: searchStatus = false
  • 在父模板中,获取child实例的#as名称或其他名称。
  • 使用#as.searchStatuschild和child中的parent更改searchStatus this.searchStatus

这种方法更好,更简单。这是继续进行的有效方法吗?为什么Angular不推广这种方法?从一个星期开始,我一直在寻找解决方案,并且到处都发现了输入/输出案例。
身体

我们称其为“模板参考变量”方式。这似乎很简单。但是测试起来可能会有点困难,并且父/子组件耦合在一起,这可能不是一件好事。就个人而言,我更喜欢BehaviorSubject方法,该方法更易于测试和解耦,并且可以设置为在父子之间传递的复杂对象的属性。旁注:angular的eventEmitter是幕后的主题。
Timathon
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.