Rodolfo
Rodolfo

Reputation: 332

Angular: Editing a specific element in a behaviour subject of type <T[]>

I got an html table showing a list of sequences, I'm populating this page using a BehaviourSubject of type Sequence[]

   private sequencesSubject = new BehaviorSubject<Sequence[]>([]);

   findSequences(pageIndex: number, pageSize: number, rrc: string): Observable<PaginatedResult> {

        return this.http.get<PaginatedResult>('https://bgpie.net/api/rrc/' + rrc + '/sequence', {
            params: new HttpParams()
                .set('page', pageIndex.toString())
                .set('limit', pageSize.toString())
        });
    }

   loadSequences(pageIndex: number,
                  pageSize: number,
                  rrc: string) {

        this.loadingSubject.next(true);

        this.sequencesService.findSequences(pageIndex, pageSize, rrc).pipe(
                /*catchError(() => of([]))*/
                finalize(() => this.loadingSubject.next(false)),
                tap(x => this.length.next(x.total))
            )
            .subscribe((sequences: PaginatedResult) => this.sequencesSubject.next(sequences.items));
    }

These are the interfaces for PaginatedResult and Sequence

export interface PaginatedResult{
  readonly items: Sequence[];
  readonly total: number;
}

My table contains a sequence in each row, this rows are expandable. When the rows expand (when i click on them) they show more data referred to that specific sequence, I want this data to be populated only when the rows are clicked. I'm trying to create a method that edits my sequencesSubject replacing the sequence i clicked on with the one i get from an http request

getSequence(id: string): Observable<Sequence> {
      return this.http.get<Sequence>('https://bgpie.net/api/sequence/' + id);
    }

I don't know how to access a specific element of the sequencesSubject replacing it with the one I get from getSequence.

Upvotes: 0

Views: 339

Answers (1)

superhawk610
superhawk610

Reputation: 2653

Retrieve the most recent value from your BehaviorSubject, replace the sequence matching id with the value you retrieve from your network call, and then emit the new array.

class SequencesList {
  private sequencesSubject = new BehaviorSubject<Sequence[]>([]);

  constructor(private http: Http, private sequencesService: SequencesService) {
    sequencesService.findSequences().subscribe(sequences =>
      this.sequencesSubject.next(sequences);
    );
  }

  async onSequenceClick(event: any) {
    const id = event.target.id;
    const sequenceWithDetails = this.http.get<Sequence>('/api/sequence/' + id);
    const sequences = this.sequencesSubject.getValue();
    const sequenceIndex = sequences.findIndex(seq => seq.id === id);
    sequences[sequenceIndex] = sequenceWithDetails;
    this.sequencesSubject.next(sequences);
  }
}

Upvotes: 1

Related Questions