3

I've created a directive

import {
  Directive, AfterContentInit, Output, EventEmitter
} from '@angular/core';

@Directive({ selector: '[attached]' })
export class AttachDirective implements AfterContentInit {

  @Output("attached")
  private ee: EventEmitter<AttachDirective> = new EventEmitter();

  ngAfterContentInit() { setTimeout(() => this.ee.next(this)); }

}

to define a custom event that should fire when a DOM element to which it is bound gets "attached" to the view. So for example <input (attached)="do something" ... does something as soon as the <input> shows up on the page.

The event fires well, my problem is however that when I'd like to access its target like <input (attached)="$event.target.something = 'anything'" I get an error such as

Cannot set property 'something' of undefined

How to upgrade my directive so I can access the target of the event?

tom
  • 2,137
  • 2
  • 27
  • 51

2 Answers2

1

there is no $event.target when you're emitting the component instance using output. You can however, emit the elementRef of your component using this.ee.next(this.elementRef)

Inject the elementRef in your constructor:

constructor(elementRef: ElementRef) { }

Joshua Chan
  • 1,797
  • 8
  • 16
  • I've imported `ElementRef`, made the changes you suggested and also changed `ee: EventEmitter` to `ee: EventEmitter` (is it ok?) but I'm still getting the same error. – tom May 26 '18 at 02:01
  • What properties are you accessing? Note that ElementRef is just the reference, the DOM's API are in elementRef.nativeElement. There are certain implications when using nativeElement in Angular. Google something known as renderer2 – Joshua Chan May 26 '18 at 02:09
  • Using `next(this.elementRef.nativeElement)` instead of `next(this.elementRef)` it works, but now I must use `$event.disabled = 'disabled'` instead of `$event.target.disabled = 'disabled'` to let's say disable the `` in the view. Or to access any other property. So which should be the target is now the $event. I tried writing next({target: this.elementRef.nativeElement}) but that's apparently not the way to do it. Any ideas? Maybe I should check Renderer2 out... – tom May 26 '18 at 02:35
1

To access the element as $event.target, define a target property that returns the HTML element to which the directive is applied:

@Output("attached") private ev: EventEmitter<AttachDirective> = new EventEmitter();

constructor(private elementRef: ElementRef) { }

public get target(): HTMLElement {
  return this.elementRef.nativeElement as HTMLElement;
}

ngAfterContentInit() {
  this.ev.next(this);
}
<input type="text" (attached)="$event.target.disabled = true" >

See this stackblitz for a demo.

ConnorsFan
  • 70,558
  • 13
  • 122
  • 146