Reputation: 682
I wrote a directive which is adding a HostListener (in this case "focus") on any component. The directive should call a method on it's host component whenever the element is on focus.
<my-component myDirective>
<h3>Hello World</h3>
</my-component>
<my-other-component myDirective>
<button>Hello</button>
</my-other-component>
The HostListener inside myDirective
@HostListener('focus')
onFocus() {
this.myService.myStream$
.pipe(first())
.subscribe((value => {
this.myHostComponent.doSomeMagic(value);
}))
}
Since it should work on every component i prefer to only implement the doSomeMagic()
method in the components and letting the myDirective doing the work with the HostListener and the observable.
Is there a way to call a method on the directives host without knowing which component it actualy is?
Upvotes: 1
Views: 3352
Reputation: 10147
You can do it with an injected component:
Something like this should work, directive.ts:
constructor(private myHostComponent: MyComponent) {}
...
this.myHostComponent.doSomeMagic(value);
You will have to know the type of component tho.
I believe it could work if you would make and abstract component from which all your doSomeMagic()
components will extend:
constructor(private myHostComponent: MyAbstractComponent) {}
class MyAbstractComponent() {
abstract doSomeMagic();
}
I'm not sure about the abstract part, you will need to check if it works.
Edit:
You can also pass the reference to the component/element via directive input. Here is a quick StackBlitz:
https://stackblitz.com/edit/angular-playground-anhhhc?file=app/directive.ts
Upvotes: 0
Reputation: 108
I would do it with @Output and emit something like this:
@Directive({ selector: '[myFocusDirective]' })
export class FocusDirective {
@Output() myFocusDirective = new EventEmitter<MouseEvent>();
constructor(private elementRef: ElementRef) {}
@HostListener('focus')
onFocus() {
this.myService.myStream$
.pipe(first())
.subscribe((value => {
this.myFocusDirective.emit(value);;
}))
}
and then to component
<input (myFocusDirective)="openDropdown()" type="text" />
Upvotes: 1