How to correctly pass props to a component with RxJS in Angular 4?

匿名 (未验证) 提交于 2019-12-03 09:52:54

问题:

Here is my component:

@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;   } }

When I change the name in input and then I am pressing save button and this.good is NOT CHANGED good. It is old good, like it was passed to the component.

I started to debug the problem. I added onInput handler. I found that when I do this instruction: this.good.name = $event.target.value; I get this error in console:

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

Here is usage of the component:

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

Here is how I receive data for this component:

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

Here is the full code of container component: here.

Thoughts: I think the problem is because Observable returns immutable structure. I don’t think it is totally bad idea, but how to handle it?

I am trying to get same behaviour there: http://plnkr.co/edit/gdxEcSvC0v6JwoLEZDkJ?p=preview. It does not reproduce. I think this is because

How to solve my problem? I don’t want to get such error. When I press save I want this.good to contain mutated object. How to achieve this?

回答1:

You could create a copy of the original object in your presentation component and emit the value of that copy onClick of save. After emiting the mutated object, the action that you dispatch should store it as payload and the reducer should take care of replacing the old object with the mutated one. That is at least the approach that I use in my presentation components :)

For example:

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);   } }


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!