J'ai un composant parent ( CategoryComponent ), un composant enfant ( videoListComponent ) et un ApiService.
J'ai la plupart de cela fonctionne bien, c'est-à-dire que chaque composant peut accéder à l'api json et obtenir ses données pertinentes via des observables.
Actuellement, le composant de liste de vidéos n'obtient que toutes les vidéos, je voudrais filtrer cela uniquement pour les vidéos d'une catégorie particulière, j'ai réussi cela en transmettant le categoryId à l'enfant via @Input()
.
CategoryComponent.html
<video-list *ngIf="category" [categoryId]="category.id"></video-list>
Cela fonctionne et lorsque la catégorie parent CategoryComponent change, la valeur categoryId est transmise via @Input()
mais j'ai besoin de détecter cela dans VideoListComponent et de demander à nouveau le tableau de vidéos via APIService (avec le nouveau categoryId).
Dans AngularJS, j'aurais fait un $watch
sur la variable. Quelle est la meilleure façon de gérer cela?
la source
Réponses:
En fait, il existe deux façons de détecter et de réagir lorsqu'une entrée change dans le composant enfant dans angular2 +:
Liens de documentation: ngOnChanges, SimpleChanges, Exemple de démonstration de SimpleChange
: Regardez ce plunker
Lien de documentation: Regardez ici .
Exemple de démonstration: regardez ce plongeur .
QUELLE APPROCHE DEVRIEZ-VOUS UTILISER?
Si votre composant a plusieurs entrées, alors, si vous utilisez ngOnChanges (), vous obtiendrez toutes les modifications pour toutes les entrées à la fois dans ngOnChanges (). En utilisant cette approche, vous pouvez également comparer les valeurs actuelles et précédentes de l'entrée qui a changé et prendre des mesures en conséquence.
Cependant, si vous voulez faire quelque chose lorsque seule une entrée particulière change (et que vous ne vous souciez pas des autres entrées), il peut être plus simple d'utiliser un configurateur de propriétés d'entrée. Cependant, cette approche ne fournit pas de méthode intégrée pour comparer les valeurs précédentes et actuelles de l'entrée modifiée (ce que vous pouvez faire facilement avec la méthode de cycle de vie ngOnChanges).
EDIT 2017-07-25: LA DÉTECTION DE CHANGEMENT ANGULAIRE PEUT TOUJOURS NE PAS SE DÉCLENCHER DANS CERTAINES CIRCONSTANCES
Normalement, la détection de changement pour setter et ngOnChanges se déclenche chaque fois que le composant parent modifie les données qu'il transmet à l'enfant, à condition que les données soient un type de données primitif JS (chaîne, nombre, booléen) . Cependant, dans les scénarios suivants, il ne se déclenchera pas et vous devrez prendre des mesures supplémentaires pour le faire fonctionner.
Si vous utilisez un objet ou un tableau imbriqué (au lieu d'un type de données primitif JS) pour transmettre des données du parent à l'enfant, la détection des modifications (à l'aide de setter ou de ngchanges) peut ne pas se déclencher, comme également mentionné dans la réponse de l'utilisateur: muetzerich. Pour des solutions, regardez ici .
Si vous mutez des données en dehors du contexte angulaire (c'est-à-dire en externe), alors angular ne sera pas au courant des changements. Vous devrez peut-être utiliser ChangeDetectorRef ou NgZone dans votre composant pour rendre angulaire conscient des changements externes et ainsi déclencher la détection des changements. Référez-vous à ceci .
la source
doSomething
méthode et prendre 2 arguments les nouvelles et les anciennes valeurs avant de réellement définir la nouvelle valeur, d'une autre manière serait de stocker l'ancienne valeur avant de définir et d'appeler la méthode après cela.Utilisez la
ngOnChanges()
méthode du cycle de vie dans votre composant.Voici les documents .
la source
MyComponent.myArray = []
, mais si une valeur d'entrée est modifiée, par exempleMyComponent.myArray.push(newValue)
, ellengOnChanges()
n'est pas déclenchée. Des idées sur la façon de saisir ce changement?ngOnChanges()
n'est pas appelé lorsqu'un objet imbriqué a changé. Peut-être que vous trouvez une solution iciJ'obtenais des erreurs dans la console ainsi que le compilateur et l'IDE lors de l'utilisation du
SimpleChanges
type dans la signature de fonction. Pour éviter les erreurs, utilisezany
plutôt le mot - clé dans la signature.ÉDITER:
Comme Jon l'a souligné ci-dessous, vous pouvez utiliser la
SimpleChanges
signature lorsque vous utilisez la notation entre crochets plutôt que la notation par points.la source
SimpleChanges
interface en haut de votre fichier?<my-user-details [user]="selectedUser"></my-user-details>
). Cette propriété est accessible à partir de la classe SimpleChanges en appelantchanges.user.currentValue
. L'avisuser
est lié au moment de l'exécution et ne fait pas partie de l'objet SimpleChangesngOnChanges(changes: {[propName: string]: SimpleChange}) { console.log('onChanges - myProp = ' + changes['myProp'].currentValue); }
Le pari le plus sûr est d'aller avec un service partagé au lieu d'un
@Input
paramètre. En outre, le@Input
paramètre ne détecte pas les modifications du type d'objet imbriqué complexe.Un exemple de service simple est le suivant:
Vous pouvez utiliser une implémentation similaire dans d'autres composants et tous vos composants partageront les mêmes valeurs partagées.
la source
@Input
paramètre @JoshuaKemmerer ne détecte pas les changements dans le type d'objet imbriqué complexe mais il le fait dans les objets natifs simples.Je veux juste ajouter qu'il existe un autre crochet Lifecycle appelé
DoCheck
qui est utile si la@Input
valeur n'est pas une valeur primitive.J'ai un tableau en tant que
Input
tel, cela ne déclenche donc pas l'OnChanges
événement lorsque le contenu change (car la vérification que fait Angular est `` simple '' et peu profonde, donc le tableau est toujours un tableau, même si le contenu du tableau a changé).J'implémente ensuite un code de vérification personnalisé pour décider si je veux mettre à jour ma vue avec le tableau modifié.
la source
veuillez essayer d'utiliser cette méthode. J'espère que cela t'aides
la source
Vous pouvez également avoir un observable qui se déclenche lors des changements dans le composant parent (CategoryComponent) et faire ce que vous voulez faire dans l'abonnement dans le composant enfant. (videoListComponent)
la source
Ici, ngOnChanges se déclenchera toujours lorsque votre propriété d'entrée change:
la source
Cette solution utilise une classe proxy et offre les avantages suivants:
ngOnChanges()
Exemple d'utilisation:
Fonction d'utilité:
la source
Si vous ne souhaitez pas utiliser la méthode ngOnChange implement og onChange (), vous pouvez également vous abonner aux modifications d'un élément spécifique par l' événement valueChanges , ETC.
});
le markForCheck () écrit en raison de l'utilisation dans cette déclaration:
la source
Vous pouvez également simplement passer un EventEmitter en entrée. Je ne sais pas si c'est la meilleure pratique, mais ...
CategoryComponent.ts:
CategoryComponent.html:
Et dans VideoListComponent.ts:
la source