Angular 2 Service + RxJS BehaviorSubject or EventEmitter

倖福魔咒の 提交于 2019-12-22 18:09:26

问题


I am new to Angular 2 and RXJS. I have a custom header component with 2 triggers (buttons) which should activate 2 different navigation directives in different parts of the application. I have created a service which registers the 2 different navigation directives and the header component subscribes to this. I wanted to know whats the best way to link the buttons in the header to call the open() and close() functions in each of the directives depending on the trigger that is clicked.

NOTE: Please note that I cannot use ViewChild or ContentChild because the navigation can be anywhere on the page. They can be in a different CustomComponent and are not necessarily children of the header component.

I can think of 2 options:

  1. Create 2 separate Observables/BehaviorSubjects for the 2 navigation directives in the Service and let the header pass the open and close messages to them and have the individual navigation directives subscribe to each of those corresponding Observables.
  2. Use EventEmitters but I am not sure how to use this approach.

Could you please suggest a good way to solve this?

Custom Component containing the Navigation:

@Component({
  selector: 'my-app',

  template: `
    <h1>{{title}}</h1>
    <my-custom-header>
      This is some text inside the header
    </my-custom-header>
    <nav custom-nav-1>Custom Nav 1</nav>
    <nav custom-nav-2>Custom Nav 2</nav>
  `
})
export class AppComponent {
  title = 'Hello!';
}

Header Component:

@Component({
  selector: 'my-custom-header',

  template: `
    <div class="container">
      This is a header
      <ng-content></ng-content>
      <div>Number of Nav Registered: {{noOfNav}}</div>
      <button type="button" (click)="toggleNav1()">Toggle Nav 1</button>
      <button type="button" (click)="toggleNav2()">Toggle Nav 2</button>
    </div>
  `,
  styles: ['.container { border: 1px solid; }'],
})
export class HeaderComponent {
  title = 'Hello!';
  noOfNav = 0;

  constructor(private navService: NavService) {}

  ngOnInit() {
    this.navService._navSubject.subscribe({
      next: (id) => {
        if(id!=0) {
          this.noOfNav++;
        }
      }
    });
  }

  toggleNav1() {
    console.log("Toggle Nav 1");
  }

  toggleNav2() {
    console.log("Toggle Nav 2");
  }
}

NavService:

@Injectable()
export class NavService {
  public _navSubject: BehaviodSubject = new BehaviorSubject<number>(0);

  registerNavId(id: number) {
    this._navSubject.next(id);
  }
}

Nav1Directive

@Directive({
  selector: '[custom-nav-1]'
})
export class NavDirective1 {
  constructor(private navService: NavService) {}

  ngOnInit() {
    this.navService.registerNavId(1);
  }

  isOpen() {
    console.log("isOpen");
  }

  open() {
    console.log("Open Nav");
  }

  close() {
    console.log("Close Nav");
  }
}

Nav2Directive:

@Directive({
  selector: '[custom-nav-2]'
})
export class NavDirective2 {
  constructor(private navService: NavService) {}

  ngOnInit() {
    this.navService.registerNavId(2);
  }

  isOpen() {
    console.log("isOpen");
  }

  open() {
    console.log("Open Nav 2");
  }

  close() {
    console.log("Close Nav 2");
  }
}

Plunker: https://plnkr.co/edit/3ISyH7ESoNlt65J56Yni?p=preview


回答1:


Since your components are loosely coupled (don't know each other) and you need some interaction between them, your approach (to use RxJS) is the most corresponding approach to angular2.

Everything goes Reactive now, even Forms.

EventEmitter is good, and simple, when you have output events from reusable components.



来源:https://stackoverflow.com/questions/39683414/angular-2-service-rxjs-behaviorsubject-or-eventemitter

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!