It seemed to be very simple: I wanted to create a component which displays a link and provides the ability to disable the link. Namely, disable the click event on the link and make it look disabled. So, how to handle the click event correctly in Angular?
In order to make the link disabled, I decided to convert it to a
span. A few minutes later the component was created:
I thought it would be the easiest to display a span when the component is disabled and a link when it is enabled. Thus I filled in the component with code:
Then I created a sample application to test the new component:
Piece of cake… Except it didn’t work:
Despite the conditions being alternatives, only the link worked – the
span was hidden. I supposed there was a problem with
disabled, so I started creating numerous variations on it, until I finally noticed the problem: the
span element was displayed under correct conditions, but without any contents.
Why? Because you can’t use the same
<ng-content> twice in a component. Only the first one will be filled with content, even if it is hidden. One of the solutions could look like this:
I put the
<ng-content> only once, in a template, which I referenced twice from both
span and link. This is one of the workarounds for referencing an
ng-content in several places in a component.
That behavior is regrettably by design, and it is explained i.a. in this bug report. Please note that this trick cannot be used to display that
ng-content more than one time in the component. I wrote about it in the consecutive post.
As you can see, now the contents is displayed correctly:
The next step was adding support for the
click event. I added it in the component and handled in the application:
Here is the component:
And sample application:
Unfortunately, when testing the application, I discovered two new problems:
Button #1 was clicked Button #1 was clicked Button #2 was clicked Button #2 was clicked Button #3 was clicked
- although the
spandid not have the
clickevent attached, that event (from the component) was fired when a user clicked the disabled link
- clicking the enabled links raised two events
At first, I ignored double events and I thought that the solution found in Google Material’s source code (button.ts) will help for the first issue. I added
_haltDisabledEvent() to the
It turned out that it helped for a real user using a web browser to not be able to fire the event, but a clever user could still click in the space around the label, still within the component. And it did not help for a unit test which checked if the component is clickable.
Another attempt also failed, even worse, as it did not prevent from clicking in any case:
Taking into consideration that even enabled component worked incorrectly (two events were fired), it led me to think that the initial approach was wrong. Probably the component should implement the ControlValueAccessor interface…
To be continued in future.