#angular #rxjs #angular2-observables #mutability
Вопрос:
Я создаю приложение Angular, в котором у меня следующая ситуация: компонент подписывается на Observable
услугу value on и отображает данные с помощью async pipe
. Он вводит значения во вложенный компонент редактирования, который, в свою очередь, отображает a reactive form
.
Моя проблема в том, что, похоже, отправка значения из формы напрямую изменяет наблюдаемый источник ( BehaviorSubject
). Есть какой-нибудь способ избежать этого? Код приведен ниже, хотя имена изменены.
data.service.ts:
export class DataService {
private dataSource = new BehaviorSubject<MyData[]>(null);
private data$ = this.dataSource.asObservable();
getDataObservable(): Observable<MyData> {
// fetch data from api, subscribe to it
// and call dataSource.next() on subscription result
}
update(data: MyData) {
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// dataSource.value IS ALREADY MUTATED HERE
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}
}
список.компонент.ts:
export class ListComponent implements OnInit {
@Input() userId: string;
data$: Observable<MyData[]>;
dataInEditing: MyData;
constructor(private dataService: DataService ) { }
ngOnInit() {
this.data$ = this.dataService.getDataObservable();
}
onDataSelected(data: MyData): void {
this.dataInEditing = data;
}
onDataEdited(data: MyData): void {
this.dataService.update(data);
this.dataInEditing = null;
}
}
list.component.html:
<div *ngIf="data$ | async as data; else loading">
<data-table</data-table> <!--inputs/outputs ommited-->
<data-edit
*ngIf="!!dataInEditing "
[data]="dataInEditing "
(dataChangedEvent)="onDataEdited($event)"></data-edit>
</div>
<ng-template #loading>Loading...</ng-template>
данные-редактировать.компонент.ts
export class DataEditComponent implements OnChanges {
@Input() data: MyData;
@Output() dataChangedEvent = new EventEmitter<MyData>();
form: FormGroup;
constructor(private fb: FormBuilder) { }
ngOnChanges(changes: SimpleChanges): void {
this.form = this.createForm();
}
updateData(): void { // onSubmit
if (this.form.valid) {
// update data
this.dataChangedEvent.emit(this.data);
}
}
private createForm(): FormGroup {
return this.fb.group({/**/});
}
}
Чтобы повторить: DataService.dataSource.value
изменились ли элементы еще до того, как я попробую сделать это вручную DataService.update()
. Это говорит мне о том, что компоненты получают ту же ссылку, которая BehaviourSubject
сохраняется. Должен ли я map
перенести наблюдаемые данные в совершенно новый массив или что-то в этом роде? Или я подхожу к этому совершенно неправильно?
Комментарии:
1. Действительно, объект BehaviorSubject дает вам точный элемент, а не копию. Вы не должны изменять его содержание. Вы можете использовать оператор распространения в операторе карты, как вы предложили.