Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

369
Views
RxJs: concat two observables as options for material select

I am having problems trying to concat two different observables and show the results into a Material Select component.

On this example (built using the tool from Material docs) there is a simple example simulating what I want to do. Options are not being shown.

In my current code (on my machine), the problem I see is: the first Observable that is passed to the concat operator is subscribed and all items are shown in the Select. But I belive that the first Observable never completes. It looks like material-select is not "completing" the first Observable and, because of that, concat won't subscribe to the next Observable while the first one never completes, as it says in its docs:

Note that if some input Observable never completes, concat will also never complete and Observables following the one that did not complete will never be subscribed.

What I need is this: taking two different Observables (with different data in each one), concat them (or any other operation), and, in the end, show all their data combined as options of a single select component.

Just as a reference, I'll copy the code here also, so it won't be lost in the future:

// Component:
import { Component, Input } from '@angular/core';
import { from } from 'rxjs';
import { concatWith } from 'rxjs/operators';

interface Option {
  value: number;
  label: string;
}

@Component({
  selector: 'select-overview-example',
  templateUrl: 'select-overview-example.html',
})
export class SelectOverviewExample {
  @Input()
  options$: any;

  constructor() {}
  ngOnInit() {
    // Let's pretend this data comes from API 1
    const sourceA$ = from([
      { value: 1, label: 'Value 1' },
      { value: 2, label: 'Value 2' },
      { value: 3, label: 'Value 3' },
    ]);

    // And these ones comes from API 2
    const sourceB$ = from([
      { value: 4, label: 'Value 4' },
      { value: 5, label: 'Value 5' },
      { value: 6, label: 'Value 6' },
    ]);

    // Now, concat the data from both observables and display all of them as options in a Select component:
    this.options$ = concatWith(sourceA$, sourceB$);
  }
}

And the template:

<h4>Basic mat-select</h4>
<mat-form-field appearance="fill">
  <mat-label>Select some value:</mat-label>
  <mat-select>
    <mat-option
      *ngFor="let option of (options$ | async)"
      [value]="option.value"
    >
      {{option.label}}
    </mat-option>
  </mat-select>
</mat-form-field>
about 4 years ago · Juan Pablo Isaza
2 answers
Answer question

0

You can collect the values from multiple observables using the merge function and the scan operator as follows:

import { from, merge } from 'rxjs';
import { scan } from 'rxjs/operators';


const sourceA$ = from(/* ... */);
const sourceB$ = from(/* ... */);

merge(sourceA$, sourceB$)
  .pipe(
    scan((acc, value) => {
      acc.push(value);
      return acc;
    }, [])
  )
  .subscribe((value) => console.log(value));

StackBlitz Example

In this example, you can replace merge with concat and it still works. If the order matters and you want to get all values from sourceA$ before subscribing to sourceB$, then you are correct that concat should be used instead of merge.

Regarding your comment...

It looks like material-select is not "completing" the first Observable

It is not the responsibility of material-select to complete the source Observable. It's the responsibility of the source Observable to complete. material-select has no way of knowing when the source Observable is done emitting values without the source Observable completing itself.

about 4 years ago · Juan Pablo Isaza Report

0

Using forkJoin and then merge the two array should be a good and clean option:

this.options$ = forkJoin([sourceA$, sourceB$]).pipe( // runs both parallel
  map(res => {
    const sA = res[0]; 
    const sB = res[1]; 
    return [...sA, ...sB]; // merges two array using the spread operator
  })
);
about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!