Como verificar o comprimento de uma matriz observável

108

No meu componente Angular 2, tenho uma matriz observável

list$: Observable<any[]>;

No meu modelo eu tenho

<div *ngIf="list$.length==0">No records found.</div>

<div *ngIf="list$.length>0">
    <ul>
        <li *ngFor="let item of list$ | async">item.name</li>
    </ul>
</div>

Mas list $ .length não funciona no caso de array Observable.

Atualizar:

Parece que (list $ | async) ?. length nos dá o comprimento, mas o código abaixo ainda não funciona:

<div>
    Length: {{(list$ | async)?.length}}
    <div *ngIf="(list$ | async)?.length>0">
        <ul>
            <li *ngFor="let item of (list$ | async)">
                {{item.firstName}}
            </li>
        </ul>
    </div>
</div>

Alguém pode orientar como faço para verificar o comprimento da matriz Observable.

Naveed Ahmed
fonte
Relatado em github.com/angular/angular/issues/9641
Günter Zöchbauer

Respostas:

178

Você pode usar o | asynctubo:

<div *ngIf="(list$ | async)?.length==0">No records found.</div>

Atualização - Versão Angular 6:

Se você estiver carregando um esqueleto css, poderá usá-lo. Se a matriz não tiver itens, ela exibirá o modelo css. Se houver dados, preencha o ngFor.

<ul *ngIf="(list$| async)?.length > 0; else loading">
   <li *ngFor="let listItem of list$| async">
      {{ listItem.text }}
   </li>
</ul>

<ng-template #loading>
  <p>Shows when no data, waiting for Api</p>
  <loading-component></loading-component>
</ng-template>
Günter Zöchbauer
fonte
4
Eu tentei isso também, mas dá o erro "TypeError: Não é possível ler a propriedade 'comprimento' de nulo"
Naveed Ahmed
3
Difícil saber pelas informações que você forneceu. Experimente <div *ngIf="(list$ | async)?.length==0">No records found.</div>(adicionado ?)
Günter Zöchbauer
6
Tentei fazer isso e funcionou <div * ngIf = "(list $ | async) ?. length == 0"> Nenhum registro encontrado. </div>
Naveed Ahmed
3
O adicional ?é necessário porque list$só é definido depois que Angular2 tenta renderizar a visualização pela primeira vez. ?evita que o resto da subexpressão seja avaliado até que a parte à esquerda de ?se torne != null(Elvis ou operador de navegação segura).
Günter Zöchbauer
1
@ GünterZöchbauer, parece-me que o primeiro asyncpipe resolve dados e, portanto, meu próximo asyncpipe no loop não exibe nada. Ou talvez *ngIfcrie um escopo adicional e, portanto, não esteja funcionando. Difícil dizer. Mas embora meu loop esteja dentro de if, ele não exibe nenhum dado. Se for avaliado truecorretamente.
Eugene
31

Uma solução para arquivos .ts:

     this.list.subscribe(result => {console.log(result.length)});
Em branco
fonte
não é necessário cancelar a inscrição imediatamente depois?
Peter,
É melhor cancelar a assinatura de observáveis ​​no onDestroycomponente
ThPadelis
16

Para Angular 4+, experimente isto

<div *ngIf="list$ | async;let list">
    Length: {{list.length}}
    <div *ngIf="list.length>0">
        <ul>
            <li *ngFor="let item of list">
                {{item.firstName}}
            </li>
        </ul>
    </div>
</div>
MD KAMRUL HASAN SHAHED
fonte
7

Embora esta resposta esteja correta

<div *ngIf="(list$ | async)?.length === 0">No records found.</div>

Lembre-se de que se estiver usando um cliente http para chamar backend (na maioria dos casos você faz), obterá chamadas duplicadas para sua API se tiver mais de uma lista $ | assíncrono . Isso ocorre porque cada | O pipe assíncrono criará um novo assinante para sua lista $ observable.

Andzej Maciusovic
fonte
4

Isto é o que funcionou para mim -

*ngIf="!photos || photos?.length===0"

Estou recebendo meus dados de httpClient async.

Todas as outras opções aqui não funcionaram para mim, o que foi decepcionante. Especialmente o cachimbo sexy (list $ | async).

Basa ..

Tzvi Gregory Kaidanov
fonte
2

Sua abordagem aqui tem outro grande problema: ao aproveitar o pipe assíncrono repetidamente em seu modelo, você está na verdade iniciando tantas assinaturas para o único Observable.

KAMRUL HASAN SHAHED tem a abordagem certa acima: use o pipe assíncrono uma vez e, em seguida, forneça um alias para o resultado que você pode aproveitar nos nós filhos.

Harry Beckwith
fonte
1

Também pode ser reduzido:

<div *ngIf="!(list$ | async)?.length">No records found.</div>

Basta usar o ponto de exclamação antes do parêntese.

Daniyal Lukmanov
fonte
-3

iônico 4

<div *ngIf="(items | async)?.length==0">No records found.</div>

funcionou quando eu removi o $sinal

Ahmed Al-hajri
fonte