@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, то не срабатывает.
  • Вопрос задан
  • 3208 просмотров
Пригласить эксперта
Ответы на вопрос 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.
Ответ написан
Комментировать
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы