Angular2:父/子组件

时间:2016-02-25 09:55:48

标签: angular

版本:" angular2":" 2.0.0-beta.6"

我想在父/子组件案例中实现双向绑定。

在我的子组件上,我使用双向绑定在编辑时显示文本。

子组件(InputTestComponent [selector:'input-test']):

<form (ngSubmit)="onSubmit()" #testform="ngForm">
    {{name}}
    <textarea #textarea [(ngModel)]="name" ngControl="name" name="name"></textarea>
    <button type="submit">Go</button>
</form>

然后,我想将此更改传播到其父组件。 我尝试使用[(name)]="name"但没有成功。

父组件:

<div>
  {{name}}
  <input-test [(name)]="name"></input-test>
</div>

Code sample

最简单的方法(更简洁)?

5 个答案:

答案 0 :(得分:35)

对于双向绑定,请使用@Input()@Output()。名称应为propNamepropNameChange以允许速记绑定语法[(propName)]="someModel",否则您需要更长的版本[propName]="someModel" (propNameOtherOutputName)="propName=$event;propNameOtherOutputName.emit($event)"

@Component{
  ...
  template: `
<textarea #textarea [(ngModel)]="name" (ngModelChange)="nameChange.emit($event)" ngControl="name" name="name"></textarea>

`})
export class InputTestComponent {
  @Output() nameChange:EventEmitter<String> = new EventEmitter<String>();
  @Input() name:string;
}

答案 1 :(得分:2)

您需要在子组件中使用输入/输出元素,如下所述:

@Component({
  selector:'input-test'
  template: `
    <form (ngSubmit)="onSubmit()" #testform="ngForm">
    {{name}}
      <textarea #textarea [(ngModel)]="name" ngControl="name" name="name"></textarea>
      <button type="submit">Go</button>
    </form>
  `
})
export class InputTestComponent {
  @Input()
  name:string;

  @Output()
  nameChange:EventEmitter<string> = new EventEmitter();
}

检测到更改时,您需要使用EventEmitter

触发事件
onSubmit() {
  this.nameChange.emit(this.name);
}

这样,使用以下语法时,父组件的绑定元素将自动更新:

<input-test [(name)]="name"></input-test>

如果您想检测输入更改而不是使用表单提交,您可以注意到可以利用ngModelChange事件:

@Component({
  selector:'input-test'
  template: `
    <form #testform="ngForm">
    {{name}}
      <textarea #textarea [ngModel]="name" (ngModelChange)="onChange($event)" ngControl="name" name="name"></textarea>
    </form>
  `
})
export class InputTestComponent {
  @Input()
  name:string;

  @Output()
  nameChange:EventEmitter<string> = new EventEmitter();

  onChange(newName) {
    this.name = newName;
    this.nameChange.emit(this.name);
  }
}

答案 2 :(得分:2)

您可以通过以下方式设置父组件和子组件之间的双向数据绑定:

<app-child [(counter)]="counter"></app-child>
<app-child [counter]="counter" (counterChange)="counter=$event"></app-child>
<app-child [counter]="counter" (counterChange)="onCounterChange($event)"></app-child>

根据Angular - Template Syntax - Two-way binding

  

Angular为此提供了一种特殊的双向数据绑定语法,   [(X)]。 [(x)]语法结合了属性绑定的括号,   [x],带有事件绑定的括号,(x)。

<app-child [(counter)]="counter"></app-child>
  

当元素具有a时,[(x)]语法很容易演示   名为x的可设置属性和名为xChange的相应事件。

@Input() counter: number;
@Output() counterChange = new EventEmitter<number>();
  

双向绑定语法实际上只是一个语法糖   属性绑定和事件绑定。 Angular desugars the   ChildComponent绑定到此:

<app-child [counter]="counter" (counterChange)="counter=$event"></app-child>

示例:https://stackblitz.com/edit/angular-two-way-data-binding-between-parent-and-child-component?file=src%2Fapp%2Fapp.component.ts

import { Component, Input, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `
  <div style="background-color: red; padding: 10px;">
    <div>{{counter}}</div>
    <button (click)="increment()">increment from parent</button>
    <app-child [(counter)]="counter"></app-child>
    <app-child [counter]="counter" (counterChange)="counter=$event"></app-child>
    <app-child [counter]="counter" (counterChange)="onCounterChange($event)"></app-child>
  </div>
  `
})
export class AppComponent {

  counter = 0;

  increment() {
    this.counter++;
  }

  onCounterChange(counter: number) {
    this.counter = counter;
  }
}

@Component({
  selector: 'app-child',
  template: `
  <div style="background-color: green; padding: 10px; margin: 10px;">
    <div>{{counter}}</div>
    <button (click)="increment()">increment from child</button>
  </div>
  `,
})
export class ChildComponent {

  @Input() counter: number;
  @Output() counterChange = new EventEmitter<number>();

  constructor() { }

  increment() {
    this.counterChange.emit(++this.counter);
  }

}

答案 3 :(得分:1)

是的,我们可以使用banana属性来共享子节点到父节点之间的数据 [(propertyname)]propertynameChange发射器事件。 样本plunker可用https://plnkr.co/edit/FYXv36?p=preview

答案 4 :(得分:0)

您可以使用@Input和@Output实现父级和子级之间的2种方式绑定,如先前的答案所述。

否则,还有另一种解决方案,您可以使用包含变量的服务,并且可以通过ngModel从不同组件(即使它们不是父子组件)同时访问它