angular - Lire un champ d'objet depuis un observable en utilisant le pipe async
Je veux mieux comprendre quand utiliser le pipe async dans Angular.
J'adore l'idée de faire apparaître les données de manière asynchrone dans la vue en ajoutant simplement un pipe qui s'abonne aux données.
Cependant, je n'ai jamais vu et appliqué correctement le pipe async que sur une requête réseau, ou un autre observable personnalisé, qui contient soit un tableau de données, soit un seul champ (comme une chaîne observable).
Par exemple :
Disons que je fais un appel API qui retourne un tableau d'étudiants universitaires.
// This data is within a network response
$students = ...get...map...
[
{
name: "Bob OConnel",
id: 0,
description: "young..."
},
{
name: "Rick Luckard",
id: 3,
description: "young..."
},
{
name: "James Wing",
id: 2,
description: "young..."
}
]
Cela pourrait être affiché dans un modèle comme ceci :
<tr *ngFor="let student of $students | async">
<td>{{student.id}}</td>
<td>{{student.name}}</td>
<td>{{student.description}}</td>
</tr>
Cependant, étant donné la philosophie REST API classique, je n'ai encore jamais fait un appel API en production qui retourne uniquement un tableau de données. Il y a toujours des champs au même niveau que le tableau de données. Mais ils sont là pour une raison, je ne veux pas simplement jeter ces champs supplémentaires dans un mappage.
Ainsi, au lieu que $students soit un tableau, cela deviendrait :
// This data is within a network response
$students = ...get...map...
{
id: "69asdkasdkljasd6969"
href: "someURLrepresentingTheDatasOrigins"
length: 3
items: [
{
name: "Bob OConnel",
id: 0,
description: "young..."
},
{
name: "Rick Luckard",
id: 3,
description: "young..."
},
{
name: "James Wing",
id: 2,
description: "young..."
}
]
}
Cela signifie donc que dans le modèle, je peux appliquer un pipe async sur l'observable $students, mais pas sur les champs à l'intérieur.
Cela ne fonctionne évidemment pas, parce que les champs au sein des observables sont des observables :
{{$students.id| async}}
// or
<tr *ngFor="let student of $students.items | async">...</tr>
Donc, est-ce que cela signifie que pour des réponses réseau comme celle-là, je devrais mapper les valeurs de la réponse dans leurs propres observables individuelles si je veux les lier de manière asynchrone dans un modèle ? Y a-t-il un moyen de contourner cela si je ne veux pas que la réponse réseau se divise en un million de petits objets (ou dans le cas de mon exemple : {id, length, href} et {items}) ?
J'ai l'impression qu'il me manque quelque chose d'évident sur l'utilisation des observables qui clarifierait ce problème pour moi. Faites-moi savoir si ma question n'est pas assez claire.
MISE À JOUR J'ai découvert quelque chose que je ne savais pas que je pouvais faire ici : https://toddmotto.com/angular-ngif-async-pipe
Super utile pour les situations où une sorte d'indicateur de chargement devrait être à la place des données asynchrones. Cela fonctionne également pour consolider les abonnements en un seul endroit. Cela serait une question de préférence, mais je pense que dans plusieurs de mes situations, je préférerais mettre l'abonnement dans un *ngIf.
À moins que vous ne puissiez faire cette même logique de else dans un *ngFor.. ?
Réponse #1
Vous n'avez pas besoin de mapper les valeurs dans leur propre observable individuel. Vous pouvez simplement envelopper votre observable entre parenthèses avec le pipe async, puis accéder aux champs à l'intérieur de l'objet renvoyé par l'observable.
Essayez :
<tr *ngFor="let student of ($students | async).items">
<td>{{student.id}}</td>
<td>{{student.name}}</td>
<td>{{student.description}}</td>
</tr>
