0

I am using angular 7 with rxjs . I have 3 tabs . In each tab , we are having some operation to be performed.

Here i am pasting the html of the dependent tab for reference.

<div class="container">
<div class="row">
<form method="POST" [formGroup]="dependentForm" enctype="multipart/form-data" class="form-horizontal col-md-12">
<div class="row">
<div class="form-group col-md-4">
<label for="Name">Name</label>
<input for="name" class="form-control" type="text" id="name" placeholder="Enter Name"
formControlName="name" />
</div>
<div class="form-group col-md-4">
<label for="relationShip">RelationShip</label>
<select class="form-control" id="relationShip" formControlName="relationShip">
<option [ngValue]="relationShip.Code" *ngFor="let relationShip of _relationShipArr">{{relationShip.Name}}</option>
</select>
</div>
<div class="form-group col-md-4 ">
<label for="dob">Date of Birth</label>
<input for="dob" class="form-control" type="text" id="dob" placeholder="Enter Date of Birth"
formControlName="dob" />
</div>
</div>
<div class="row">
<div class="form-group col-md-4">
<label for="Address">Address</label>
<textarea class="form-control" rows="1"
formControlName="address" id="address" placeholder="Enter Address"></textarea>
</div>
<div class="form-group col-md-4">
<label for="contactNumber">Contact Number</label>
<input for="contactnumber" class="form-control" type="text" id="contactNumber"
placeholder="Enter Contact Number" formControlName="contactNumber" />
</div>
<div class="form-group col-md-2 align-self-end">
<button class="btn btn-block btn-primary" type="submit" (click)="SaveDependent()" [disabled]="!dependentForm.valid">
<i class="fa fa-fw fa-save"></i>Add</button>
</div>
<div class="form-group align-self-end col-md-2">
<button type="submit" class="btn btn-block btn-primary" (click)="ClearDependent()">
<i class="fa fa-fw fa-undo"></i>Reset</button>
</div>
</div>
</form>
</div>
<div class="row">
<table class="table table-bordered table-hover col-md-12">
<thead>
<tr>
<th>Name</th>
<th>RelationShip</th>
<th>Date of Brith</th>
<th>Contact Number</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let dependent of dependents|async" (click)="SelectDependent(dependent)">
<td>{{dependent.Name}}</td>
<td>{{dependent.RelationShip|statusformat:"relationShip"}}</td>
<td>{{dependent.Dob}}</td>
<td>{{dependent.ContactNumber}}</td>
</tr>
</tbody>
</table>
</div>
</div>

I am using reactive form to add the dependent details in this tab. The same tab i have table which is populated from a service call GetDependents (Service code is attached below) which uses BehaviourSubject . So it will read only once from API.

import { Injectable } from '@angular/core';
import { IMember } from '../models/imember';
import { BaseService } from 'src/app/framework/baseservice';
import { BehaviorSubject } from 'rxjs';
import { switchMap, shareReplay } from 'rxjs/operators';
import { IDependent } from '../models/idependent';
import { IDonation } from '../models/idonation';

@Injectable()
export class MemberService extends BaseService {

private _dependentSubject: BehaviorSubject<Array<IDependent>>;


constructor(protected http: HttpClient) { 
super();
this._dependentSubject=new BehaviorSubject<Array<IDependent>>(null);
}

GetDependents(memberId:number){
let ob = this.http.get<Array<IDependent>>(this.urlResolver(`Member/Dependents/${memberId}`));
return this._dependentSubject.pipe(switchMap(()=>ob),shareReplay(1));
}
AddDependent(dependent:IDependent)
{

}
}

If you see in the html i have a add button which add each dependent detail to the table. And this should intern append to the BehaviourSubject. Then again should refresh the table.

How do i achieve this. I don't want to call save the dependent API on add . All the dependent add should hold in memory.

There is a common save button for the whole tab that should save the entire change.

chairmanmow
  • 649
  • 7
  • 20
Vipin
  • 938
  • 5
  • 18
  • 36
  • I don't fully understand your question, but you are losing the benefit of `shareReplay` by constructing a new `pipe` each time and returning it within `GetDependents`. – Ian MacDonald Mar 07 '19 at 20:47
  • @IanMacDonald Thanks for replying. I will explain again. I am having 3 tab. In one of the tab add Dependent detail to a html table. We can have existing data in this table; which will be read only once with the help of an api. So when i add values, It should refresh the table . But added value should not go to database. I used Behaviour Subject to hit only once the dependent API. So that dependent will be cached even if i switch tab. – Vipin Mar 07 '19 at 20:54

2 Answers2

1

In order to update the value of the BehaviorSubject, you push a new value with .next. You could fetch the current value with .value, but instead, I prefer to use .pipe(take(1)).

private _dependentSubject: BehaviorSubject<Array<IDependent>>;

constructor(protected http: HttpClient) { 
  super();
  this._dependentSubject = new BehaviorSubject<Array<IDependent>>(null);

  this.http.get<Array<IDependent>>(this.urlResolver(`Member/Dependents/${memberId}`))
      .pipe(map((response: any) => /* map to Array<IDependent> */)
      .subscribe((result: Array<IDependent>) => this._dependentSubject.next(result));
}

get dependents(): Observable<Array<IDependent>> {
  return this._dependentSubject.asObservable();
}

AddDependent(dependent:IDependent)
{
  this._dependentSubject.pipe(take(1))
      .subscribe((dependents: Array<IDependent>) => {
        /* TODO: deal with null value when http get hasn't returned yet */
        dependents.push(dependent);
        this._dependentSubject.next(dependents);
      });
}

You may want to look into resolvers to ensure that your data is loaded prior to this component beginning execution so there isn't a period of time that you're waiting for a server response and holding null in your BehaviorSubject.

Ian MacDonald
  • 13,472
  • 2
  • 30
  • 51
-3

Inside your AddDependent method you can add this line for pushing data

this._dependentSubject.next([...this._dependentSubject.getValue(), ...dependent]);

It merge your new value with previous value. Here I use spread operator.

  • Using `getValue()` is considered as a red flag. See https://stackoverflow.com/a/37089997/10070613 – David Jul 10 '20 at 05:37