239 votes

Événements globaux dans Angular

N'y a-t-il pas un équivalent à $scope.emit() o $scope.broadcast() dans Angular ?

Je sais que le EventEmitter mais, d'après ce que j'ai compris, cela ne fera qu'émettre un événement vers l'élément HTML parent.

Que faire si j'ai besoin de communiquer entre frères et sœurs fx. ou entre un composant situé dans la racine du DOM et un élément imbriqué à plusieurs niveaux de profondeur ?

2 votes

J'avais une question similaire concernant la création d'un composant de dialogue auquel on pouvait accéder à partir de n'importe quel point du domaine : stackoverflow.com/questions/34572539/ En gros, une solution consiste à placer un émetteur d'événements dans un service

1 votes

Voici mon implémentation d'un tel service en utilisant RXJS qui permet d'obtenir les nièmes dernières valeurs sur abonnement. stackoverflow.com/questions/46027693/

2voto

Andrea Martines Points 41

Ma méthode préférée consiste à utiliser un sujet de comportement ou un émetteur d'événements (presque la même chose) dans mon service pour contrôler tous mes sous-composants.

En utilisant angular cli, exécuter ng g s pour créer un nouveau service puis utiliser un BehaviorSubject ou EventEmitter

export Class myService {
#all the stuff that must exist

myString: string[] = [];
contactChange : BehaviorSubject<string[]> = new BehaviorSubject(this.myString);

   getContacts(newContacts) {
     // get your data from a webservices & when you done simply next the value 
    this.contactChange.next(newContacts);
   }
}

Lorsque vous faites cela, chaque composant utilisant votre service en tant que fournisseur sera conscient du changement. Il suffit de s'abonner au résultat comme vous le faites avec eventEmitter ;)

export Class myComp {
#all the stuff that exists like @Component + constructor using (private myService: myService)

this.myService.contactChange.subscribe((contacts) => {
     this.contactList += contacts; //run everytime next is called
  }
}

1voto

zakrzu Points 331

C'est ma version :

export interface IEventListenr extends OnDestroy{
    ngOnDestroy(): void
}

@Injectable()
export class EventManagerService {

    private listeners = {};
    private subject = new EventEmitter();
    private eventObserver = this.subject.asObservable();

    constructor() {

        this.eventObserver.subscribe(({name,args})=>{

             if(this.listeners[name])
             {
                 for(let listener of this.listeners[name])
                 {
                     listener.callback(args);
                 }
             }
        })

    }

    public registerEvent(eventName:string,eventListener:IEventListenr,callback:any)
    {

        if(!this.listeners[eventName])
             this.listeners[eventName] = [];

         let eventExist = false;
         for(let listener of this.listeners[eventName])
         {

             if(listener.eventListener.constructor.name==eventListener.constructor.name)
             {
                 eventExist = true;
                 break;
             }
         }

        if(!eventExist)
        {
             this.listeners[eventName].push({eventListener,callback});
        }
    }

    public unregisterEvent(eventName:string,eventListener:IEventListenr)
    {

        if(this.listeners[eventName])
        {
            for(let i = 0; i<this.listeners[eventName].length;i++)
            {

                if(this.listeners[eventName][i].eventListener.constructor.name==eventListener.constructor.name)
                {
                    this.listeners[eventName].splice(i, 1);
                    break;
                }
            }
        }

    }

    emit(name:string,...args:any[])
    {
        this.subject.next({name,args});
    }
}

utiliser :

export class <YOURCOMPONENT> implements IEventListener{

  constructor(private eventManager: EventManagerService) {

    this.eventManager.registerEvent('EVENT_NAME',this,(args:any)=>{
       ....
    })

  }

  ngOnDestroy(): void {
    this.eventManager.unregisterEvent('closeModal',this)
  }

}

émettent :

 this.eventManager.emit("EVENT_NAME");

1voto

TGH Points 15623

J'ai créé un échantillon de pub-sub ici :

http://www.syntaxsuccess.com/viewarticle/pub-sub-in-angular-2.0

L'idée est d'utiliser RxJs Subjects pour mettre en place un observateur et des observables comme solution générique pour émettre et s'abonner à des événements personnalisés. Dans mon exemple, j'utilise un objet client pour les besoins de la démonstration.

this.pubSubService.Stream.emit(customer);

this.pubSubService.Stream.subscribe(customer => this.processCustomer(customer));

Voici également une démo en direct : http://www.syntaxsuccess.com/angular-2-samples/#/demo/pub-sub

0voto

Peter Rigole Points 161

Nous avons mis en place une directive observable ngModelChange qui envoie toutes les modifications du modèle par le biais d'un émetteur d'événements que vous instanciez dans votre propre composant. Il vous suffit de lier votre émetteur d'événements à la directive.

Voir : https://github.com/atomicbits/angular2-modelchangeobservable

En html, liez votre émetteur d'événements (countryChanged dans cet exemple) :

<input [(ngModel)]="country.name"
       [modelChangeObservable]="countryChanged" 
       placeholder="Country"
       name="country" id="country"></input>

Dans votre composant typescript, effectuez quelques opérations asynchrones sur l'EventEmitter :

import ...
import {ModelChangeObservable} from './model-change-observable.directive'

@Component({
    selector: 'my-component',
    directives: [ModelChangeObservable],
    providers: [],
    templateUrl: 'my-component.html'
})

export class MyComponent {

    @Input()
    country: Country

    selectedCountries:Country[]
    countries:Country[] = <Country[]>[]
    countryChanged:EventEmitter<string> = new EventEmitter<string>()

    constructor() {

        this.countryChanged
            .filter((text:string) => text.length > 2)
            .debounceTime(300)
            .subscribe((countryName:string) => {
                let query = new RegExp(countryName, 'ig')
                this.selectedCountries = this.countries.filter((country:Country) => {
                    return query.test(country.name)
                })
            })
    }
}

-1voto

Événements de service : Les composants peuvent s'abonner aux événements des services. Par exemple, deux composants frères et sœurs peuvent s'abonner au même événement de service et répondre en modifiant leurs modèles respectifs. Plus d'informations à ce sujet ci-dessous.

Mais assurez-vous de vous désinscrire de ce système en détruisant le composant parent.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X