Reputation: 349
Is it possible to bind to data inside an observable and maintain the data in both directions?
For example: I have some kind of dialog where the user can enter some kind of data. And the layout of the dialog gets loaded from a configuration and is inside an observable. The configuration contains which input fields will be shown.
So i tried to use the async
pipe inside my dialog template. Rendering the fields works like a charm but i tried to databind to values inside the observable aswell. Each time a close and open the dialog now i get a new observable and loose my data.
To avoid loosing data i subscribe to the observable in my service and write it to a data object:
export class DataService implements OnInit {
private data: any = {};
ngOnInit() {
this.http.get(path).subscribe((myData) => {
this.data.data = myData;
}
}
//other code ...
//opening the dialog this way
const dialogRef = this.dialog.open(MyDialogComponent, {
width: '1200px',
data: this.dataService.getData()
});
//Using data in the dialog template
<div *ngIf="data.data as myField; else loading">
<mat-form-field>
<input #inputText matInput
placeholder="{{ myField.name }}"
[(ngModel)]="myField.value"
name="{{ myField.name }}"
matTooltip="{{myField.description}}"
[required]="myField.required">
</mat-form-field>
</div>
<ng-template #loading>
<mat-spinner mode="indeterminate" diameter="30"></mat-spinner>
</ng-template>
I could also separate data from my model but that would make the processing a lot harder.
Are there any other options to handle requirement? What would be the best practice?
Upvotes: 1
Views: 473
Reputation: 11345
Use shareReplay(1) is a cleaner solution and get its value using async
pipe, it acts like BehaviourSubject.
export class DataService implements OnInit {
private data: any = {};
ngOnInit() {
this.data.data=this.http.get(path).pipe(shareReplay(1))
}
//other code ...
//opening the dialog this way
const dialogRef = this.dialog.open(MyDialogComponent, {
width: '1200px',
data: this.dataService.getData()
});
<div *ngIf="(data.data | async) as myField; else loading">
<mat-form-field>
<input #inputText matInput
placeholder="{{ myField.name }}"
[(ngModel)]="myField.value"
name="{{ myField.name }}"
matTooltip="{{myField.description}}"
[required]="myField.required">
</mat-form-field>
</div>
<ng-template #loading>
<mat-spinner mode="indeterminate" diameter="30"></mat-spinner>
</ng-template>
Upvotes: 1
Reputation: 4247
Have you thought of re-broadcasting it in a ReplaySubject?
export class DataService implements OnInit {
private data = new ReplaySubject<any>;
ngOnInit() {
this.http.get(path).subscribe((myData) => {
this.data.next(myData);
}
}
public getMyData() {
return Observable.of(this.myData);
}
Upvotes: 1