Angular2 метод вызова другого компонента

У меня есть приложение Angular2, в котором я создал компонент заголовка, который отображается в моем основном компоненте приложения.

Теперь у меня есть другой компонент Form, который должен иметь свою кнопку отправки, помещенную в заголовок. Как я могу это сделать?

Мне нужно общаться между кнопкой отправки в заголовке и методом отправки компонента Form. Я знаю, что тривиально выполнять родительское > дочернее или дочернее > родительское общение, но в этом случае между моими компонентами Header и Form нет отношений между родителями и дочерними элементами, а также отношения между сестрами.

Мое дерево компонентов выглядит следующим образом:

- app-root
  |-- app-header // -> this is where the submit button is
  |-- app-edit-profile
      |-- app-profile-form // -> this is my form

Есть ли у кого-нибудь представление о возможной реализации?

Ответ 1

Вы можете создать одну услугу, которая будет использоваться между вашим заголовком и компонентом формы, в котором вы можете определить Observable, чтобы вы могли подписаться на эту форму Observable из формы и выполнить некоторые действия, когда вы получите некоторое значение из заголовка.

common.service.ts

import { Injectable, Inject } from '@angular/core';
import { Subject }    from 'rxjs/Subject';
@Injectable()
export class CommonService {
  private notify = new Subject<any>();
  /**
   * Observable string streams
   */
  notifyObservable$ = this.notify.asObservable();

  constructor(){}

  public notifyOther(data: any) {
    if (data) {
      this.notify.next(data);
    }
  }
}

header.component.ts

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs/Subscription';

import { CommonService } from './common.service';

@Component({
  selector   : 'header',
  templateUrl : './header.html'
})
export class HeaderComponent implements OnInit, OnDestroy {
  constructor( private commonService: CommonService ){
  }

  ngOnInit() {       
  }

  onSubmit(){
    // this method needs to be called when user click on submit button from header
    this.commonService.notifyOther({option: 'onSubmit', value: 'From header'});
  }
}

form.component.ts

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs/Subscription';

import { CommonService } from './common.service';

@Component({
  selector   : 'form',
  templateUrl : './form.html'
})
export class FormComponent implements OnInit, OnDestroy {
  private subscription: Subscription;
  constructor( private commonService: CommonService ){
  }

  ngOnInit() {
    this.subscription = this.commonService.notifyObservable$.subscribe((res) => {
      if (res.hasOwnProperty('option') && res.option === 'onSubmit') {
        console.log(res.value);
        // perform your other action from here

      }
    });
  }

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

Ответ 2

Помимо решения с Observable, я думаю, что важно сказать что-то о EventEmitters, как они, на мой взгляд, проще в использовании в таких сценариях.

В дочернем контроллере

импортировать типы EventEmitter и Output.

import { EventEmitter, Output } from "@angular/core

объявить свойство вывода типа EventEmitter

@Output() formSubmit$: EventEmitter<boolean>;

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

this.formSubmit$ = new EventEmitter();

и, наконец, с надлежащим действием, связанным с кнопкой отправки, вызвать метод "emit" EventEmitter для распространения события через ваше приложение:

this.formSubmit$.emit(true);

В родительском контроллере

В родительском представлении привяжите событие formSubmit $к действию контроллера:

<child-selector (formSubmit$)="handleFormSubmit($event)"></child-selector>

затем объявите метод в контроллере

public handleFormSubmit(submit: boolean): void {
    alert("Form has been submitted! Do your stuff here!");
}

Очевидно, что эту стратегию можно использовать только, когда вам нужно обмениваться данными с дочерним элементом на родительский контроллер.

Ответ 4

Использование услуг и предметов - самый простой способ. Если вы хотите сохранить запись своих данных, вы можете даже использовать тему воспроизведения

private notify: ReplaySubject<any> = new ReplaySubject<any>();

Но вы можете даже попробовать библиотеку, называемую eventbus. Я столкнулся с теми же проблемами, и eventbus - это правильный ответ для этого.