Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why passing $event in Angular (when dealing with DOM events) is a dubious practice

I was reading Angular 2 documentation where I found:

Passing the $event is not a good practice

Typing the event object reveals a significant objection to passing the entire DOM event into the method: the component has too much awareness of the template details. It can't extract information without knowing more than it should about the HTML implementation. That breaks the separation of concerns between the template (what the user sees) and the component (how the application processes user data).

For some reason I can't exactly fit my head around what it says. Seems like there are no explanation available either anywhere.

Can someone explain the exact meaning of this in simpler terms (with an example, if possible)?

like image 652
Saurabh Tiwari Avatar asked Apr 17 '17 15:04

Saurabh Tiwari


People also ask

What is the use of $event in Angular?

The $event object often contains information the method needs, such as a user's name or an image URL. The target event determines the shape of the $event object. If the target event is a native DOM element event, then $event is a DOM event object, with properties such as target and target.

What is event and $event in Angular?

In Angular 8, event binding is used to handle the events raised by the user actions like button click, mouse movement, keystrokes, etc. When the DOM event happens at an element(e.g. click, keydown, keyup), it calls the specified method in the particular component.

What is the type of $event in Angular?

Angular includes $event that contains the information about an event. The type of $event depends on the target event, e.g., if the target event is a native DOM element event, then it is an object. A component should define the onShow(event) method where the type of the parameter can be KeyboardEvent, MouseEvent, etc.

What is DOM events in Angular?

HTML DOM events allow JavaScript to register different event handlers on elements in an HTML document. Events are normally used in combination with functions, and the function will not be executed before the event occurs (such as when a user clicks a button).


1 Answers

Look at the examples the docs already provide for before and after:

@Component({
  selector: 'key-up1',
  template: `
    <input #box (keyup)="onKey($event)">
    <p>{{values}}</p>
  `
})
export class KeyUpComponent_v1 {
  values = ''; 

  onKey(event: KeyboardEvent) {
    this.values += (<HTMLInputElement>event.target).value + ' | ';
  }
}

Here the component has to know that the event has a target, which is an input element, which has a value. Now v2:

@Component({
  selector: 'key-up2',
  template: `
    <input #box (keyup)="onKey(box.value)">
    <p>{{values}}</p>
  `
})
export class KeyUpComponent_v2 {
  values = '';

  onKey(value: string) {
    this.values += value + ' | ';
  }
}

Here the template is responsible for extracting the correct value from its own structure, and all the component knows is that it's getting a string. Now imagine:

  1. You need to change the input element to a select, to restrict the range of inputs. What has to change in each version? Just the template, or does the component have to change too?

  2. You want to test the handling method. How easy is this for each version? Can you just pass in a string, or do you have to build an event with an element of the appropriate structure?

This is what separation of concerns really means - how far does a change propagate? How much does each piece of your system need to know about the other pieces to continue working? Per Wikipedia, for example:

Of special value is the ability to later improve or modify one section of code without having to know the details of other sections, and without having to make corresponding changes to those sections.


However, as snorkpete suggests, note that the reservation around passing $event to component methods only applies when $event refers to DOM events. In the case where you're using an EventEmitter to raise your own events, $event will (most likely) be an object from the business domain, and is perfectly fine to use as is.

like image 113
jonrsharpe Avatar answered Oct 16 '22 08:10

jonrsharpe