1

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?

3
  • 1
    Here is a full github thread explaining it. Commented Jan 30, 2019 at 8:35
  • I'm voting to close this question as off-topic because it is already answered on github Commented Jan 30, 2019 at 8:36
  • why not, in your directive, call a function in your service that emit a value? then, subscribe to the service in your component (I hope this has any sense) Commented Jan 30, 2019 at 9:18

2 Answers 2

1

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" />
Sign up to request clarification or add additional context in comments.

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.