Naming of @Output events in Angular
We should be very careful when declaring an output event in an Angular component, especially with the name of the Output decorator. Bad names could lead to unpredictable behavior and difficult to detect bugs. In this article, I will describe a similar case that happened to myself and cost me hours of debugging.
The application
Consider the following application that consists of two Angular components communicating each other using an output event.
The first one, ExportComponent
, contains a textarea element with some arbitrary text and a select element. The component emits a select
output event when the value of the select element changes.
The second component, AppComponent
, which is the main component of the application, binds to the select
event of theExportComponent
and sets its msg
property when emitted.
Let’s try this
Select a value from the dropdown menu and the application displays the following message:
Export fired from [object HTMLSelectElement]
This looks quite reasonable and our components communicate perfect. That’s nice! Now try to select some text from the text area. You will notice that the message changes to:
Export fired from [object Event]
Huh?
This should not happen! Why is that? Well, the answer lies in the MDN web docs about theselect
native event. As it states:
The
select
event fires when some text has been selected.The event is not available for all elements in all languages. For example, in HTML,
select
events can be dispatched only on form<input type="text">
and<textarea>
elements.
That is, by giving our output event the name select, we accidentally created a conflict with the select
native event of the textarea element.
Conclusion
We should not use output and input names that collide with either a native property/event name or even an input/output name used by any other component or directive. We should give a name that clearly conveys the meaning of the event, as Angular Material does with theselectionChange
event of the MatSelect element. You can find the list of standard native events that you should avoid here.
I hope you will find this article useful as it did for me. Have you encountered such a situation with input and output names? Let me know on the comments below!
UPDATE: If you use TSLINT, you can install codelyzer (which I highly recommend) and enable no-output-named-after-standard-event
. To do this, open tslint.json
inside your app
folder and add the following line inside the rules
section:
“no-output-named-after-standard-event”: true
Enabling this switch, will warn you when you are trying to use a native event name as an output name inside a component, either during development or when running the ng lint
command.