Rodolfo
Rodolfo

Reputation: 332

Angular - How to put one single object<T> in a BehaviorSubject<T[]>

I have a data table populated by a BehaviorSubject<Sequence[]>, here's how it works:

//sequencesService

findSequences(pageIndex: number, pageSize: number, rrc: string, datiForm: FormComponent): Observable<PaginatedResult>{
    return this.http.get<PaginatedResult>('https://bgpie.net/api/rrc/' + rrc + '/sequence', { params});
    }

//dataSource
export class SequencesDataSource implements DataSource<Sequence> {

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

    private loadingSubject = new BehaviorSubject<boolean>(false);

    public loading$ = this.loadingSubject.asObservable();

    public length = new BehaviorSubject<number>(0);

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

        this.loadingSubject.next(true);

        this.sequencesService.findSequences(pageIndex, pageSize, rrc, datiForm).pipe(
                finalize(() => this.loadingSubject.next(false)),
                tap(x => this.length.next(x.total))
            )
            .subscribe((sequences: PaginatedResult) => {
            this.sequencesSubject.next(sequences.items);
        });}
    }

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

I would like to be able to filter the table using the sequence Id as a criteria. This means that only one sequence would have to be shown. While the method findSequences calls for an API containing an array of sequences, the method below calls for an API with a single sequence, as it should be:

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

The problem is that I can't use an observable of type Sequence to populate a BehaviorSubject<Sequence[]>. I tried returning an observable of type Sequence[] (like in the code below) and then subscribing to it but it doesn't work.

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

//dataSource
loadSequence(datiForm: FormComponent){
        this.loadingSubject.next(true);

        this.sequencesService.getSequenceFilter(datiForm.sequenceId).pipe(
            finalize(() => this.loadingSubject.next(false)),
            finalize(() => this.length.next(1))
        )
        .subscribe((sequence: Sequence[]) => this.sequencesSubject.next(sequence))

Upvotes: 0

Views: 50

Answers (2)

you could next unique sequence instance as array

this.sequencesSubject.next([sequence])

instead of single object

this.sequencesSubject.next(sequence)

Full function modified

loadSequence(datiForm: FormComponent){
        this.loadingSubject.next(true);

        this.sequencesService.getSequenceFilter(datiForm.sequenceId).pipe(
            finalize(() => this.loadingSubject.next(false)),
            finalize(() => this.length.next(1))
        )
        .subscribe((sequence: Sequence) => this.sequencesSubject.next([sequence]))

Upvotes: 1

Benny Halperin
Benny Halperin

Reputation: 2332

Do the following simple changes:

  1. Have getSequence(id: string) return Observable<Sequence>
  2. In loadSequence method change to .pipe(......., map(sequence => [sequence]), tap(sequence => this.sequencesSubject.next(sequence))).subscribe()

Upvotes: 1

Related Questions