Задать вопрос
@RomanChasovitin
Front-End developer

Как вызвать метод компонента из другого компонента?

Всем доброго утра! Возник небольшой вопрос. У меня есть компонент, в котором есть кнопка, которая при клике должна триггерить событие в другом компоненте. Вложенность компонентов очень большая ( 1>1>1>1>1>comp1 и 1>2>2>2>2>comp2). Решил сделать это через Subject. При клике вызываю метод в сервисе, который делает моему Subject'у next(). также в сервисе есть метод, который возвращает этот Subject. Так вот, все работает и subject успешно делает next() и при подписке на него в самом сервисе все отрабатывает отлично. Но возникает проблема, как подписаться на Subject во втором компоненте? Если при onInit или onChange, то не срабатывает.
  • Вопрос задан
  • 3401 просмотр
Подписаться 1 Сложный 1 комментарий
Пригласить эксперта
Ответы на вопрос 2
Xuxicheta
@Xuxicheta Куратор тега Angular
инженер
компонент 1
constructor (
  private myService: MyService,
) {}
onMyButton() {
  this.myService.triggerOnMyButton();
}

компонент 2
constructor (
  private myService: MyService,
) {}
ngOnInit() {
  this.myService.trigger$.subscribe(() => this.myMethod());
}

сервис
private _trigger = new Subject<void>();
get trigger$() {
  return this._trigger.asObservable();
}
public triggerOnMyButton() {
  this._trigger.next();
}


и, тут этого не отражено, не забывайте отписываться
Ответ написан
@Pantene742
Subject или Через Redux если используется ngrx. Еще если компоненты грузятся через контейнер. то вместо компонент оутлет можно сделать референцию

В компоненте :

component: any;

@ViewChild('mainContent', { read: ViewContainerRef })
  mainContent: ViewContainerRef;


загрузить компонент в контейнер как через оутлет в коде компонента:
this.mainContent.createComponent(this.cF.resolveComponentFactory(Название компонента из переменной как для компонент оутлета тип -> ComponentRef);

в переменную копонент заносим данны компонент:
this.component = this.mainContent.createComponent(this.cF.resolveComponentFactory(Название компонента из переменной как для компонент оутлета тип -> ComponentRef);


Даллее.....this.component.instance.MethodFromComponent() И нам будут доступны все свойства и методы в загруженые в контейнер. Также методы могут быть async и вызывать их надо
await this.component.instance.MethodFromComponent()
Но такой способ нам понадобился по той причине что каждый компонент загруженный в контейнер имел методы с одинаковым названием. В родителе стелки назад - вперед. И мы как бы в текущем дочернем понимали юзер хочет вернутся назад или пойти дальше, если при вызове возращался фолс мы не пускали назад или вперед не переключали на новый компонент. В дочерних были onGoBack и onGoNext и если на goNext форма оказывается не валидной вывод ошибки и возращение false и родитель знает что не надо переключать на следующий.

Еще вариант из стаковерфлоу.
Когда не используется загрузка компонента через отлет в контейнер а метод вставляется в родителя хардкодом.
@Component({
  selector: 'child-cmp',
  template: '<p>child</p>'
})
class ChildCmp {
  doSomething() {}
}
@Component({
  selector: 'some-cmp',
  template: '<child-cmp #child></child-cmp>',
  directives: [ChildCmp]
})
class SomeCmp {
  @ViewChild('child') child:ChildCmp;
  ngAfterViewInit() {
    // child is set
    this.child.doSomething();
  }
}


Из чайлда в парент луше всего стукать через оутпут. И такое нереально чтоб чайлд знал методы парента(как выше) так как чайлды для повторного использования. (Костыль во всех случаях) Да и то что више также костыль. Для масимальной читаемости проекта Redux или Subject. Так же где логично Input Output.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы