Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

368
Vistas
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 Respuestas
Responde la pregunta

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 Denunciar

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 Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda