Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

393
Visualizações
Angular display template if observable is falsey with async pipe

I have an API call that may return some data or may return something falsey if no data exists. If there is data, I want to tap out of the stream and do some side effects, but if falsey, I want no side effects to happen but still display my template code.

I am using an async pipe to get that data in the template, but if the data is falsey, it will not display.

I have seen the technique to wrap the ngIf with an object so it evaluates to truthy, but it doesn't seem the correct solution for my code.

My template:

<form *ngIf="loadedData$ | async">
  ...
</form>

My class:

loadedData$: Observable<boolean>;

ngOnInit(): void {
  this.loadedData$ = this.getCurrentBranding().pipe(
    tap(branding => {
      if (branding) {
        // Do side effects
      }
    }),
    // current hack to make the template show
    map(() => true)
  );
}

private getCurrentBranding(): Observable<Branding> {
  // API call, may return an object, or null
}
over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

You can always try to keep it as semantic as possible. Your approach using map is not a bad idea, it's just that you actually lose the access to your data. It's probably better to split it up in two Observables:

readonly data$: Observable<BrandingData> = this.getCurrentBranding().pipe(
  tap((branding) => { /* Do side effects */ }),
  shareReplay({ refCount: true, bufferSize: 1 })
);

readonly loadingData$: Observable<boolean> = this.data$.pipe(
  mapTo(false),
  startWith(true)
);

You can then show your form by checking if the data is being loaded:

<form *ngIf="(loadingData$ | async) === false"></form>

What happens here is that by subscribing to the loadingData$ in the template, actually also subscribes to the data$ osbervable, which will trigger the API request. By using shareReplay, you make sure that this request is only done once on every subscribe.

over 4 years ago · Santiago Trujillo Relatório

0

the "typical" is use an object as "if" in the way

<!--see that the if is always "true" -is an object- -->
<form *ngIf="{response:loadedData$ | async} as res">
   <!--you has the response in res.response-->
   <ng-container *ngIf="res.response===false">
      the result of the call is false
   </ng-container>
   <ng-container *ngIf="res.response!===false">
    {{res.response|json}}
   </ng-container>
</form>
over 4 years ago · Santiago Trujillo Relatório

0

I've been getting in the habit of having a single observable for my component that merges multiple streams, combining them into one state. Usually this involves the scan operator, but in this case it's not necessary (though maybe you want to merge in these side effects too).

In the code below getCurrentBranding will execute when it is subscribed to by the async pipe in the component. To prevent multiple executions you can have one root element that uses Angular's as expression to convert the emission into a template variable. Alternatively, you could use shareReplay.

The startWith operator is used to provide an initial value, so the root element will always be displayed. The form will initially be hidden until the result is returned from the api. The data will come from the same observable and access from the template variable created at the root element.

this.state$ = this.getCurrentBranding().pipe(
  tap(branding => { /* Do side effects */ ),
  map(data => ({ data, isLoaded: true}),
  startWith(({ data: [], isLoaded: false})
);
<ng-container *ngIf="(state$ | async) as state">
  <form *ngIf="state.isLoaded">
    <!-- ... -->
  </form>
  <ol *ngFor="let o of state.data">
    <!-- ... -->
  </ol>
</ng-container>
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda