2017-08-22 9 views
1

J'essaye d'implémenter le type de modèle Observer en utilisant EventEmitter dans Angular.Créer EvenEmitter dynamiquement en Angular

Par exemple, j'ai un éditeur appelé component1Publisher

component1Publisher: EventEmitter<any> = new EventEmitter(); 

publier les événements comme ci-dessous

this.component1Publisher.emit(data); 

Abonnez-vous à plusieurs composants comme ci-dessous

component1Publisher.subscribe((data:any) => { 
      //do something here; 

      }); 

Vous pouvez voir la l'éditeur est statique Dans mon projet, l'éditeur et subsciber est complètement dynamique. Donc, je veux créer cette instance de EventEmitter et abonné sur la base de mon name.Something unique composant comme ci-dessous

createEvent(uniqueName:string){ 
//new unique eventEmitter 
} 

Mon problème J'ai un cadre réutilisable pour créer un tableau de bord que l'utilisateur peut apporter des widgets fournis par le cadre lui-même. J'essaie donc de communiquer entre les widgets pour le rendre interactif. Par exemple, lorsque vous cliquez sur le widget doit notifier tous les autres widgets. Pour ce faire, je prévois de dire à l'utilisateur de fournir un service dynamique. En service dynamique, ayez une méthode comme onWidgetClick(), qui se déclenchera par framework en résolvant dynamiquement le service. Dans cette méthode, l'utilisateur peut créer un événement à publier. Il notifiera tous les widgets avec les nouvelles données et le framework le mettra à jour avec de nouvelles données (tous les widgets réutilisables ont l'abonné).

Pourriez-vous s'il vous plaît aidez-moi à ce sujet ou suggérer est-il une alternative à faire ce genre de mise en œuvre

+0

La question mise à jour avec l'exigence réelle – JEMI

Répondre

1

Je définirais une carte (je pense que c'est le bon terme?) À l'intérieur quel que soit le composant/directive « ceci » fait référence à. Quelque chose comme:

componentPublishers: { [index:string] : EventEmitter<any> } = {}; 

ce code dit juste, je crée un objet qui contiendra eventEmitters, tous identifiés par des chaînes (vous pouvez utiliser des chaînes ou des nombres comme identifiants, mais dans presque tous les cas, les gens utiliser des chaînes).

Ensuite, vous pouvez ajouter EventEmitters avec n'importe quel nom, en utilisant la notation de parenthèse (qui est utilisée dans JS pour ajouter de nouvelles propriétés aux objets). Après sa création, vous devriez pouvoir y accéder comme d'habitude sans notation de parenthèse.En utilisant la carte comme je l'ai montré ci-dessus, les caractères dactylographiés sauront que toute propriété de l'objet componentPublishers sera un émetteur d'événement.

this.componentPublishers.myNewEventEmitter.emit('some value'); 

Remarque: vous obtenez des erreurs si vous essayez d'utiliser la notation support pour ajouter des propriétés à l'objet, si vous n'instancier premier. Je l'ai juste instancié comme un objet vide.

... = {}; 

Alors assurez-vous de le faire.

Vous pouvez aussi simplement créer un tableau d'émetteurs d'événements et y ajouter de nouveaux émetteurs, mais cela devient très maladroit car vous devez garder une trace des indices. En utilisant une carte, vous pouvez y accéder par nom comme un objet régulier, tout en conservant la vérification de type statique de Typescript.

+0

C'est bon pour moi. Laissez-moi essayer cette solution. J'ai mis à jour ma question avec l'exigence réelle. Pensez-vous que la solution fournie par @DeborahK répondra à mes besoins. Je ne pense pas sans observable que ce n'est pas possible – JEMI

+1

Je pense que vous avez raison observables serait la meilleure solution. Vous pouvez également essayer de créer des sujets rxjs au lieu de EventEmitters. Ils peuvent être plus faciles à gérer, et ils vous donnent plus d'options. Une autre chose qui pourrait vous aider ... vous pouvez traiter les abonnements impérativement en important 'Abonnement' depuis 'rxjs/Subscription'. Cela peut vous épargner un peu de codage répétitif si vous envoyez constamment des Observables et que le destinataire est immédiatement abonné à eux dans la plupart des cas. Il vous permet également de vous désabonner si le widget/composant/quel qu'il soit est détruit. – diopside

+0

Je suis d'accord sur le fait que j'ai vu quelque part en utilisant rxJS Subjects. Merci pour votre solution. Je vais essayer la même chose. – JEMI

1

Selon ce que vous essayez d'accomplir en fin de compte, cela peut ne pas être nécessaire. Vous pouvez tirer parti de la détection des modifications d'Angular pour fournir les notifications dont vous avez besoin.

Par exemple, vous pouvez configurer un service comme celui-ci:

import { Injectable } from '@angular/core'; 

@Injectable() 
export class DataService { 
    serviceData: string; 
} 

Tous les modèles liés à ces données sont automatiquement informés des modifications (pas d'événement) nécessaires.

J'ai un billet de blog à ce sujet ici: https://blogs.msmvps.com/deborahk/build-a-simple-angular-service-to-share-data/

Et plunker ici: https://plnkr.co/edit/KT4JLmpcwGBM2xdZQeI9?p=preview

+0

est le cadre de sorte que l'utilisateur devrait avoir une option pour créer un événement basé sur le nom du composant. Le framework souscrit déjà avec le nom unique. Donc, à chaque fois que vous publiez un événement, c'est tout le composant qui est souscrit. Dans mon événement de pensée, l'émetteur est le mieux adapté à cette exigence. – JEMI

+0

J'ai mis à jour ma question avec mes besoins réels – JEMI