это - eventemitter angular 6




Делегирование: EventEmitter или Observable in Angular (5)

Я пытаюсь реализовать что-то вроде шаблона делегирования в Angular. Когда пользователь нажимает на элемент nav-item , я хотел бы вызвать функцию, которая затем генерирует событие, которое, в свою очередь, должно обрабатываться другим компонентом, прослушивающим событие.

Вот сценарий: у меня есть компонент Navigation :

import {Component, Output, EventEmitter} from 'angular2/core';

@Component({
    // other properties left out for brevity
    events : ['navchange'], 
    template:`
      <div class="nav-item" (click)="selectedNavItem(1)"></div>
    `
})

export class Navigation {

    @Output() navchange: EventEmitter<number> = new EventEmitter();

    selectedNavItem(item: number) {
        console.log('selected nav item ' + item);
        this.navchange.emit(item)
    }

}

Вот компонент наблюдения:

export class ObservingComponent {

  // How do I observe the event ? 
  // <----------Observe/Register Event ?-------->

  public selectedNavItem(item: number) {
    console.log('item index changed!');
  }

}

Ключевой вопрос заключается в том, как заставить компонент наблюдения наблюдать за рассматриваемым событием?


Вам необходимо использовать компонент Navigation в шаблоне ObservingComponent (не забудьте добавить селектор в компонент Navigation. Компонент для навигации, например)

<navigation-component (navchange)='onNavGhange($event)'></navigation-component>

И реализовать onNavGhange () в ObservingComponent

onNavGhange(event) {
  console.log(event);
}

И последнее ... вам не нужен атрибут events в @Componennt

events : ['navchange'], 

Вы можете использовать BehaviourSubject, как описано выше, или есть еще один способ:

вы можете обрабатывать EventEmitter следующим образом: сначала добавьте селектор

import {Component, Output, EventEmitter} from 'angular2/core';

@Component({
// other properties left out for brevity
selector: 'app-nav-component', //declaring selector
template:`
  <div class="nav-item" (click)="selectedNavItem(1)"></div>
`
 })

 export class Navigation {

@Output() navchange: EventEmitter<number> = new EventEmitter();

selectedNavItem(item: number) {
    console.log('selected nav item ' + item);
    this.navchange.emit(item)
}

}

Теперь вы можете обрабатывать это событие, например , предположим, что наблюдающий.component.html является представлением компонента Observer.

<app-nav-component (navchange)="recieveIdFromNav($event)"></app-nav-component>

затем в ObservingComponent.ts

export class ObservingComponent {

 //method to recieve the value from nav component

 public recieveIdFromNav(id: number) {
   console.log('here is the id sent from nav component ', id);
 }

 }

Я нашел другое решение для этого случая, не используя Reactivex ни услуги. Я действительно люблю API rxjx, но думаю, что он лучше всего подходит для разрешения асинхронных и / или сложных функций. Используя это таким образом, это довольно превзошло меня.

Я думаю, что вы ищете для трансляции. Только то. И я нашел это решение:

<app>
  <app-nav (selectedTab)="onSelectedTab($event)"></app-nav>
       // This component bellow wants to know when a tab is selected
       // broadcast here is a property of app component
  <app-interested [broadcast]="broadcast"></app-interested>
</app>

 @Component class App {
   broadcast: EventEmitter<tab>;

   constructor() {
     this.broadcast = new EventEmitter<tab>();
   }

   onSelectedTab(tab) {
     this.broadcast.emit(tab)
   }    
 }

 @Component class AppInterestedComponent implements OnInit {
   broadcast: EventEmitter<Tab>();

   doSomethingWhenTab(tab){ 
      ...
    }     

   ngOnInit() {
     this.broadcast.subscribe((tab) => this.doSomethingWhenTab(tab))
   }
 }

Это полный рабочий пример: https://plnkr.co/edit/xGVuFBOpk2GP0pRBImsE


Вы можете использовать либо:

  1. Поведение Тема:

BehaviorSubject - это тип субъекта, субъект - это особый тип наблюдаемого, который может выступать в качестве наблюдаемого, и наблюдатель, которого вы можете подписать на сообщения, как и любое другое наблюдаемое, и после подписки возвращает последнее значение субъекта, излученное наблюдаемым источником:

Преимущество: для передачи данных между компонентами не требуется таких отношений, как отношения родитель-потомок.

НАВ СЕРВИС

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

@Injectable()
export class NavService {
  private navSubject$ = new BehaviorSubject<number>(0);

  constructor() {  }

  // Event New Item Clicked
  navItemClicked(navItem: number) {
    this.navSubject$.next(number);
  }

 // Allowing Observer component to subscribe emitted data only
  getNavItemClicked$() {
   return this.navSubject$.asObservable();
  }
}

НАВИГАЦИОННЫЙ КОМПОНЕНТ

@Component({
  selector: 'navbar-list',
  template:`
    <ul>
      <li><a (click)="navItemClicked(1)">Item-1 Clicked</a></li>
      <li><a (click)="navItemClicked(2)">Item-2 Clicked</a></li>
      <li><a (click)="navItemClicked(3)">Item-3 Clicked</a></li>
      <li><a (click)="navItemClicked(4)">Item-4 Clicked</a></li>
    </ul>
})
export class Navigation {
  constructor(private navService:NavService) {}
  navItemClicked(item: number) {
    this.navService.navItemClicked(item);
  }
}

НАБЛЮДАЮЩИЙ КОМПОНЕНТ

@Component({
  selector: 'obs-comp',
  template: `obs component, item: {{item}}`
})
export class ObservingComponent {
  item: number;
  itemClickedSubcription:any

  constructor(private navService:NavService) {}
  ngOnInit() {

    this.itemClickedSubcription = this.navService
                                      .getNavItemClicked$
                                      .subscribe(
                                        item => this.selectedNavItem(item)
                                       );
  }
  selectedNavItem(item: number) {
    this.item = item;
  }

  ngOnDestroy() {
    this.itemClickedSubcription.unsubscribe();
  }
}

Второй подход - Event Delegation in upward direction child -> parent

  1. Использование декораторов @Input и @Output для передачи родительских данных дочернему компоненту и родительскому компоненту, уведомляющему о дочерних процессах.

например, ответ от @Ashish Sharma.


Последние новости: я добавил еще один ответ, который использует Observable, а не EventEmitter. Я рекомендую ответить на этот вопрос. И на самом деле, использование EventEmitter в сервисе - плохая практика .

Оригинальный ответ: (не делай этого)

Поместите EventEmitter в сервис, который позволяет ObservingComponent напрямую подписываться (и отписываться) на событие :

import {EventEmitter} from 'angular2/core';

export class NavService {
  navchange: EventEmitter<number> = new EventEmitter();
  constructor() {}
  emit(number) {
    this.navchange.emit(number);
  }
  subscribe(component, callback) {
    // set 'this' to component when callback is called
    return this.navchange.subscribe(data => call.callback(component, data));
  }
}

@Component({
  selector: 'obs-comp',
  template: 'obs component, index: {{index}}'
})
export class ObservingComponent {
  item: number;
  subscription: any;
  constructor(private navService:NavService) {
   this.subscription = this.navService.subscribe(this, this.selectedNavItem);
  }
  selectedNavItem(item: number) {
    console.log('item index changed!', item);
    this.item = item;
  }
  ngOnDestroy() {
    this.subscription.unsubscribe();
  }
}

@Component({
  selector: 'my-nav',
  template:`
    <div class="nav-item" (click)="selectedNavItem(1)">item 1 (click me)</div>
  `,
})
export class Navigation {
  constructor(private navService:NavService) {}
  selectedNavItem(item: number) {
    console.log('selected nav item ' + item);
    this.navService.emit(item);
  }
}

Если вы попробуете Plunker , есть несколько вещей, которые мне не нравятся в этом подходе:

  • ObservingComponent необходимо отписаться, когда он будет уничтожен
  • мы должны передать компонент в метод subscribe() чтобы он был установлен при вызове обратного вызова.

Обновление: альтернатива, которая решает 2-ую пулю, состоит в том, чтобы ObservingComponent напрямую подписывался на свойство navchange :

constructor(private navService:NavService) {
   this.subscription = this.navService.navchange.subscribe(data =>
     this.selectedNavItem(data));
}

Если мы подписываемся напрямую, нам не понадобится метод subscribe() в NavService.

Чтобы сделать NavService немного более инкапсулированным, вы можете добавить метод getNavChangeEmitter() и использовать его:

getNavChangeEmitter() { return this.navchange; }  // in NavService

constructor(private navService:NavService) {  // in ObservingComponent
   this.subscription = this.navService.getNavChangeEmitter().subscribe(data =>
     this.selectedNavItem(data));
}






event-delegation