问题
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