juste un exemple pour mon problème: - Le parent a child1 et child2.
Je montre une liste de mois dans un tableau, onLoad de child2.
en cliquant sur les boutons à child1, les mois seront pop n push.
en cliquant sur un bouton sur child1, il émet une nouvelle valeur au parent et plus loin cette valeur ira du parent à child2.ts et mettre à jour le tableau du mois
Le problème est que j'obtiens une erreur lors de la communication du parent à child2. J'ai utilisé la méthode d'abonnement observable et elle dit
////////////// parent.html////////////////////////////////////////// < child2 class="row-items" [navigatedMonths]="months">< /child2> < child1(navigateMonths)='navigatedMonths($event)'> Next Month< /child1>
Voici mon code.
////////////////child1.ts/////////////////////////////////// onClick() { this.navigateMonths.emit(this.month); } ////////////// parent.ts////////////////////// months: Subject < void > = new Subject < void > (); navigatedMonths(months) { this.months = months; this.months.asObservable(); } /////////child2.ts//////////////////////// @Input() navigatedMonths: Observable < void > ; ngOnInit() { this.navigatedMonths.subscribe((months) => { this.months = months; }) this.getMonths(this.year, this.month); }
this.months.asObservable is not a function
3 Réponses :
quickfix - se débarrasser des observables / sujets qui ne sont pas nécessaires
export class MonthsService { // private for internal use private monthsSource: BehaviorSubject<string[]> = new BehaviorSubject([]); // init with empty array // public for use in components or other services months$: Observable<string[]> = this.monthsSource.asObservable(); addMonth(newMonth: string) { const months = [...this.monthsSource.getValue(), newMonth]; // Create new months array this.monthsSource.next(months); } }
Vous devriez probablement envisager d'introduire un service qui est partagé entre les deux enfants. Le parent n'a pas besoin de connaître les mois.
Le service pourrait ressembler comme ceci:
////////////// parent.ts////////////////////// months: any[]; // no subject anymore navigatedMonths(months) { this.months = months; } /////////child2.ts//////////////////////// @Input() set navigatedMonths(months: any[]) { // make a setter from your input // Do whatever you want when new months come in }
Exemple complet: https://stackblitz.com/edit/ng-zorro-antd-start-ddozvn
Maintenant, les fils n'ont plus d'entrées ou de sorties, le composant parent reste propre. Chaque composant qui s'intéresse aux données s'abonne simplement aux mois $ observable.
Comment dois-je le réparer? Je suis confus maintenant
navigatedMonths (mois) {this.months = mois; this.months.asObservable (); /////// c'est une erreur}
Ahhh je vois. this.months n'est pas un sujet observable à ce stade. .asObservable ne fonctionne que sur les sujets
Je viens d'ajouter la solution à ma réponse qui utilise un service de conservation des données des mois
Le scénario que vous avez mentionné peut être réalisé en émettant des données de child1 vers parent
(en utilisant eventEmitters)
enfant1.ts
ngOnInit(){ this.myService.mySubject.subscribe((data)=>{ this.months.push(data); console.log(this.months); }); }
puis de parent à enfant2
(en utilisant @viewChild).
parent.ts
this.myService.mySubject.next(this.months[this.i++])
enfant2.ts
mySubject = new Subject();
Démo de travail ajoutée: démo
Remarque : la sortie du tableau des mois de child2 peut être vue sur la console.
Modifier: Suite est la deuxième méthode utilisant Subject
dans service
. Cette méthode peut être utilisée pour tous les types d'interactions de composants. Qu'il s'agisse d'interactions parent-enfant
ou enfant-parent
ou frères et sœurs
.
Vous devez suivre les étapes suivantes: p>
myService.ts
Créer un sujet en service. (Le sujet doit être importé de rxjs)
months:any[] = []; @Input() childMessage: string; addMonth(month){ this.months.push(month); console.log(this.months); }
enfant1.ts
Ajouter / envoyer un élément au sujet en utilisant next()
:
message:string; @ViewChild(Child2Component) child; receiveMessage($event) { this.message = $event this.child.addMonth(this.message); }
enfant2.ts
Abonnez-vous à Subject pour lire l'élément:
i = 0; months = ["jan","feb","march","april"]; @Output() messageEvent = new EventEmitter<string>(); sendMessage() { this.messageEvent.emit(this.months[this.i]); this.i++; }
Pouvez-vous l'expliquer? C'est intéressant mais pas capable de comprendre comment cela fonctionne pour un parent à enfant2
@developer ViewChild permet à un composant d'être injecté dans un autre, donnant au parent l'accès à ses attributs et fonctions. Donc, avec la référence child2 dans le parent, j'appelle sa fonction addMonth () pour ajouter des mois au tableau de child2.
Pouvons-nous le faire en utilisant un abonnement? Le développeur principal a dit que vous utilisiez parentcomponent.childComponent.childFunction (), ce qui n'est pas la bonne approche
vous devriez vraiment lire ceci: angular.io/guide/component-interaction :) Cette page aussi montre la solution Himanshu Singh comme possibilité. Mais comme mentionné dans ma réponse, je préférerais opter pour la solution de service (où le service contient un sujet de mois et quel que soit le composant qui l'intéresse, il peut y souscrire). Votre aîné sera heureux;)
Une autre option consiste à utiliser la liaison bidirectionnelle avec @Input ()
, @Output ()
et EventEmitter
. En donnant à votre @Output ()
EventEmitter
le même nom que vous @Input ()
et en ajoutant Change
au name, vous pouvez obtenir une liaison bidirectionnelle.
<app-child1 [(message)]="message"></app-child1> <app-child2 [(message)]="message"></app-child2>
@Input() public message: Message; @Output() public messageChange: EventEmitter<Message> = new EventEmitter<Message>(); public text: string; send() { if (this.text.trim().length > 0) { this.messageChange.emit(new Message(`Child1: ${this.text}`)); } }
https://stackblitz.com/edit/angular-46ndlt
https://medium.com/ @ preethi.s / angular-custom-two-way-data-binding-3e618309d6c7