如何在Angular 4中使用RxJS正确地将道具传递给组件?

时间:2017-06-13 23:20:40

标签: angular rxjs ngrx angular-components

这是我的组件:

@Component({
  selector: 'bc-goods-detail',
  template: `
    <span>good id: {{good?.id}}</span>
    <input [value]="good?.name" (input)="onInput($event)" />
    <button (click)="onClick()">Save</button>
  `,
  styles: []
})
export class GoodsDetailComponent {
  @Input() good: Good;
  @Output() save  = new EventEmitter<Good>();

  onClick() {
    this.save.emit(this.good);
  }

  onInput ($event) {
    this.good.name = $event.target.value;
  }
}

当我在输入中更改名称然后我按下保存按钮时,this.good未变好。它是旧的good,就像传递给组件一样。

我开始调试问题。我添加了onInput处理程序。我发现当我执行此指令时:this.good.name = $event.target.value;我在控制台中收到此错误:

ERROR TypeError: Cannot assign to read only property 'name' of object '#<Object>'
    at GoodsDetailComponent.webpackJsonp.435.GoodsDetailComponent.onInput (goods-detail.ts:24)

以下是组件的用法:

<bc-goods-detail
  [good]="selectedGood$ | async"
  (save)="onSave($event)"
></bc-goods-detail>

以下是我接收此组件数据的方法:

/*…*/
selectedGood$: Observable<Good>;

constructor(private store: Store<fromRoot.State>) {
  /*…*/
  this.selectedGood$ = store.select(fromRoot.getGoodSelectedEntity);
}

以下是容器组件的完整代码:here

思考:我认为问题是因为Observable返回不可变结构。我认为这不是一个坏主意,但如何处理呢?

我试图在那里得到同样的行为:http://plnkr.co/edit/gdxEcSvC0v6JwoLEZDkJ?p=preview。它不会重现。我想这是因为

如何解决我的问题?我不想得到这样的错误。当我按下save时,我希望this.good包含变异对象。怎么做到这一点?

1 个答案:

答案 0 :(得分:3)

您可以在演示文稿组件中创建原始对象的副本,并在单击“保存”时发出该副本的值。在发出mutated对象之后,您调度的操作应该将其存储为有效负载,而reducer应该负责用变异的对象替换旧对象。这至少是我在演示组件中使用的方法:)

例如:

export class GoodsDetailComponent {
  private _original: Good;
  goodClone: Good; // use this inside of the component template
  @Input('good')
  get good(){return this.goodClone;}
  set good(value:  Good){
    this.goodClone= //generate a clone of the object
    this._original = value;
  }

  @Output() 
  save  = new EventEmitter<Good>();

  onClick() {
    this.save.emit(this.goodClone);
  }
}