6

With locker service activated I'm seeing following error occurring in my components:

HTML event such as onclick no longer provides target information for a div or a button element.

For example:

I have following cmp:

<!-- myCmp -->
<div onclick="{!c.someFunction}" data-myData="something">

</div>

Controller:

//My Controller
someFunction : function(cmp,event,helper){
    var target = event.currentTarget;
    var myData = target.dataset.myData;
}

The above function throws an error because dataset is undefined.

At least two weeks ago, with locker service enabled this was still working. As of today I noticed it's no longer working.

Looking at the event.currentTarget or event.target object there is no actual data on there except some locker service functions.

Is this no longer supported in Locker service?

If I look at input fields it seems you can still access the attributes, using event.target.value to obtain the field value.

EDIT

Screen shot of event.target

enter image description here

  • Is your div inside an aura:iteration or aura:if? If so, that is a known issue with LockerService. You can open a case to track and tell them to link to internal work item W-3206803. – TrevorBliss Jun 30 '16 at 1:18
  • Yea its inside an iteration. I indeed noticed its not complaining when used outside. Thanks. – Lieven Juwet Jun 30 '16 at 16:09
7

I'm faced with the same problem. I'm doing an aura:iteration to create a list of < th > with an onclick="{!c.func}". Since I don't know how to pass a paramater to said func, I was using the data attributes. Come LockerService, it stopped working.

I've asked somewhat the same question and got a reply that it's a known SF issue and they're working on it:

https://salesforce.stackexchange.com/a/129468/31984

And there's already an open case about it:

https://success.salesforce.com/issues_view?id=a1p3A00000183rMQAQ

Either way, I found a workaround for now:

Creating a mini component which extends the original component (thus has access to the same JS Controller and helper), and putting the < th > with onclick as the markup of the new component. After that replacing all the < th > in the original component with instances of this new mini component, and instead of using a data attribute, just pass the value as a parameter to the inner component. Once the function gets called from one of the inner components, it will raise an application event to be caught by all the other instances of the inner component to check whether their 'key argument' matches whatever was fired by the event, and perform the appropriate action (add/remove class in my case, on objects I now have access to due to not being inside the aura namespace).

Here's some code (hopefully didn't miss anything copy pasting):

appEvent.evt:

<aura:event type="APPLICATION">
    <aura:attribute name="containerGId" type="String" />
    <aura:attribute name="fieldName" type="String" />
</aura:event>

innerComp.cmp

<aura:component>
    <aura:attribute name="containerGId" type="String" />
    <aura:attribute name="fieldName" type="String" />
    <aura:registerEvent name="appEvt" type="c:appEvent" />
    <aura:handler event="c:appEvent" action="{!c.catchSomething}" />
    <th aura:id='columnHeaders' onclick="{!c.fireSomething}">{!v.fieldName}</th>
</aura:component>

mainComp.cmp

<...>
<tr>
    <aura:iteration items="{!v.fieldNames}" var="fieldName">
        <c:innerComp containerGId="{!globalId}" fieldName="{!fieldName}" />
    </aura:iteration>
<tr>
<...>

innerCompController.js

({
    fireSomething : function(component, event, helper) {
        helper.fireSomething(component);
    },

    catchSomething : function(component, event, helper) {
        var evtContainerGId = event.getParam("containerGId");
        var cmpContainerGId = component.get("v.containerGId");

        if (evtContainerGId === cmpContainerGId) {
            var cmpFieldName = component.get("v.fieldName");
            var evtFieldName = event.getParam("fieldName");
            var headerElement = component.find("columnHeaders").getElement();

            if (evtFieldName === cmpFieldName) {
                $A.util.addClass(headerElement, 'slds-is-sorted');
            }
            else {
                $A.util.removeClass(headerElement, 'slds-is-sorted');
            }

innerCompHelper.js

({
    fireSomething : function(component) {
        var appEvent = $A.get("e.appEvent");
        var containerGId = component.get("v.containerGId");
        var fieldName = component.get("v.fieldName");
        appEvent.setParams({ "containerGId" : containerGId, "fieldName" : fieldName });
        appEvent.fire();
    }
}) 

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.