I'm facing issue with click event bubbling in Lightning.
I have div and inside of it few components including lightning checkbox and <a href>
tag:
Component:
<div aura:id="container" class="slds-tree__item" onclick="{!c.onToggleExpand}">
...
<aura:if isTrue="{!v.node.checkboxDisplayed}">
<ui:inputCheckbox class="inline" aura:id="nodeCheckbox" value="{!v.node.selected}" disabled="{!!v.node.checkboxEnabled}" change="{!c.onCheckboxChange}" click="{!c.onCheckboxClick}"/>
</aura:if>
...
<a href="javascript:void(0);" onclick="{!c.onNodeClick}" tabindex="-1" role="presentation">{!v.node.name}</a>
</div>
I have handlers in controller for each function, I've simplified them for the sake of brevity:
Controller:
onToggleExpand: function(component, event, helper) {
console.log('onToggleExpand');
}
onNodeClick: function(component, event, helper) {
console.log('onNodeClick');
event.stopPropagation();
}
onCheckboxChange: function(component, event, helper) {
console.log('onCheckboxChange');
event.stopPropagation();
}
onCheckboxClick: function(component, event, helper) {
console.log('onCheckboxClick');
event.stopPropagation();
console.log('end');
}
When I click checkbox, in the console I get debugs in following order:
onCheckboxClick
end
onToggleExpand
onCheckboxChange
So, the event.stopPropagation() is totally ignored. What I suppose happens here is that click on child lightning checkbox causes onCheckboxClick
handler to execute, but stopping propagation inside this method does not stop standard JS click propagation to parent div. My theory is backed up by fact that when clicking <a href>
element, onNodeClick
executes and the event is kept from propagating.
Does anyone had similar problems and has workaround for such problems? I could of course change ui:inputCheckbox
to SLDS HTML version, but I would prefer to use Lightning components. Maybe something from Lightning that could replace <div>
?
—-UPDATE:—-
I have tried with changing ui:inputCheckbox
component to standard SLDS HTML <input type="checkbox">
tag. The code looks like that:
<div aura:id="container" class="slds-tree__item" onclick="{!c.onToggleExpand}">
...
<div class="slds-form-element__control">
<span class="slds-checkbox">
<input type="checkbox" id="{!'node-checkbox-' + v.node.id}" checked="{!v.node.selected}" onchange="{!c.onCheckboxChange}" onclick="{!c.onCheckboxClick}" disabled="{!!v.node.checkboxEnabled}"/>
...
So standard HTML in both cases. I expect after clicking checkbox first onCheckboxClick
is executed and then event is blocked from bubbling up to div element because event.stopPropagation()
is used. However, that is not the case. Handlers are executed in following order:
onToggleExpand
onCheckboxClick
onCheckboxChange
WTF Lightning?
Best Answer
I still don't know why
event.stopPropagation()
does not work in this case, but I have solution how to fix the problem.SLDS checkbox uses well-known CSS technique that hides
<input type="checkbox">
element and showslabel
element that is styled with fancy images to override default checkbox look. Below the code:The trick is to put your
onclick
in correct place - if you do it on whole<span class="checkbox">
, then no problems with event bubbling will occur. Puttingonclick
oninput
will cause click event to "leak" outside checkbox because this isn't the element that uses actually clicks.--
Btw, I've made additional tests on
ui:inputCheckbox
andlightning:input type="checkbox"
. Unfortunately, in this case - that is you want onclick on parent div that is ignoring child checkbox clicks - you cannot use these components, HTML markup is needed.