Event emitter from StencilJS to Angular

丶灬走出姿态 提交于 2021-01-29 13:20:29

问题


I need to listen the event that a child component fired. In my case, I have a "tabs" component made in stencil v1 that has this structure...

abc-tabs.tsx

import { Component, h, Listen, Element, State, Event, Method, EventEmitter } from '@stencil/core';

@Component({
  tag: 'abc-tabs'
})
export class AepTabs {
  @Element() tabs: HTMLElement;
  @State() initIndex: number = 0;
  @Event() tabClick: EventEmitter; // <---------- HERE
  private tabsElements;
  private tabsElementList: Array<any> = [];
  private tabTitleElements: any;

  componentWillLoad() {
    this.createTabsTitles(this.tabs.querySelectorAll('abc-tab'));
  }

  componentDidLoad() {
    this.addTitleEvents();
  }

  addTitleEvents() {
    this.tabTitleElements = this.tabs.getElementsByClassName('tab-title');
    [].forEach.call(this.tabTitleElements, (tab, pos) => {
      tab.addEventListener('click', () => {
        this.tabClick.emit(tab);
        this.activeTabs(pos);
      });
    });
    this.activeTabs(this.initIndex);
  }

  createTabsTitles(tabsList: NodeList) {
    this.tabsElements = tabsList;
    [].forEach.call(this.tabsElements, tab => {
      this.tabsElementList.push(
        <div class="tab-title" data-automation={tab.titletab.toString().toLowerCase()}>
          <span>{tab.titletab}</span>
        </div>
      );
    });
  }

  @Method()
  activeTabs(index: number) {
    this.tabTitleElements = this.tabs.getElementsByClassName('tab-title');
    [].forEach.call(this.tabTitleElements, (tab, pos) => {
      if (index === pos) {
        tab.classList.add('active');
        tab.classList.remove('inactive');
      } else {
        tab.classList.remove('active');
        tab.classList.add('inactive');
      }
    });

    [].forEach.call(this.tabsElements, (tab, pos) => {
      if (index === pos) {
        tab.classList.add('active');
        tab.classList.remove('inactive');
      } else {
        tab.classList.remove('active');
        tab.classList.add('inactive');
      }
    });
  }

  // HERE --------------------------------------------------------
  @Listen('tabClick') 
  clicktabHandler(event: CustomEvent) {
    this.activeTabs(event.detail);
  }
  // HERE --------------------------------------------------------

  render() {
    return (
      <div>
        <nav>{this.tabsElementList}</nav>
        <div>
          <div>
            <slot />
          </div>
        </div>
      </div>
    );
  }
}

So, in my angular project I using the stencil component.

detail.component.html

<abc-tabs>
  <abc-tab titletab="My first tab">
    <!-- content here -->
  </abc-tab>
  <abc-tab titletab="My second tab" >
    <!-- content here -->
  </abc-tab>
</abc-tabs>

And everything works perfect, but now I need to @Listen (in Angular) the event that is fired up when some of the tabs was clicked, so I was doing this in my detail.component.ts class:

detail.component.ts

import { Component, OnInit } from '@angular/core';
import { Listen, Watch } from '@stencil/core';

@Component({
  selector: 'app-detail',
  templateUrl: './detail.component.html'
})
export class DetailComponent implements OnInit {
  constructor() {}

  ngOnInit() {}

  @Listen('tabClick') // <--- ERROR HERE
  clicktabHandler(event: CustomEvent) {
    console.log('has clicked!!!! ', event.detail);
  }
}

but, it throws an error in detail.component.ts:

ERROR Error: Uncaught (in promise): TypeError: Object(...) is not a function
TypeError: Object(...) is not a function

It seems that 'clicktab' it's something that Angular can not see even if I import @Listen from @stencil/core.

Any hint?


回答1:


You should use @HostListener('tabClick') instead of @Listen('tabClick').




回答2:


@Listen is the Stencil directive and @HostListener is an Angular directive. Please use the correct directive in the appropriate project.



来源:https://stackoverflow.com/questions/59002660/event-emitter-from-stenciljs-to-angular

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