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();
}
})
When locker service is in place, the golden rule is:
you cannot access the DOM of the components you do not own
Why this is enforced?
It is mainly to preserve the component encapsulation, so that developer can not accidentally/intentionally access the other developers component(one's they do not own) or even in worst case break other components functionality and also others security related stuffs are involved too.
Here a blog which details constraints imposed to access DOM, when locker service is in place.
Since the <ui:inputTextArea/>
component belongs to the ui namspace, to which do not have access to its DOM.To solve this, you can use the <textarea/>
HTML tag instead of the former.
Below is the code which I tried:
Jquery - V2.2.4
Nicescroll - V3.6.8
Component:
<aura:component controller="FullCalendarController" implements="force:appHostable" access="public">
<ltng:require scripts="/resource/jquery224,/resource/nicescroll" afterScriptsLoaded="{!c.afterScriptsLoaded}" />
<ltng:require styles="/resource/SLDS202/assets/styles/salesforce-lightning-design-system.css"/>
<aura:attribute name="isResourcesLoaded" type="Boolean"/>
<aura:attribute name="test" type="String" default="hello world"/>
<div class="slds">
<div class="slds-form-element__control textarea-wrapper">
<textArea aura:id="editModeScrollBarY" maxlength="255"
class="slds-textarea scrollbar-outer" onblur="{!c.updateNoteValue}">{!v.test}</textArea>
</div>
</div>
</aura:component>
Controller.js
({
afterScriptsLoaded: function(cmp,evt,helper){
cmp.set("v.isResourcesLoaded",true);
},
updateNoteValue : function(cmp,event){
//manully set the attribute value.
cmp.set("v.test",event.currentTarget.value);
}
})
Helper:
addScroll : function(component){
if(component.get("v.isResourcesLoaded")){
//Do Not use $(".scrollbar-outer") selector, it will break the component encapsulation.
//Because jquery will search for the DOM in whole the document rather than your component.
$(component.find("editModeScrollBarY").getElement()).niceScroll({
boxzoom:false,
autohidemode:false,
cursorcolor:"#9c9c9c",
nativeparentscrolling: true
});
}
}
Renderer:
({
afterRender: function(component, helper) {
this.superAfterRender();
},
rerender: function(component, helper) {
this.superRerender();
helper.addScroll(component);
}
})
--Update--
Even though the native scrollbar is replaced with custom scroll but I tried few things to make the content inside the textarea to scroll with locker service turned on but it did not work. :-(
P.S: I observe the same behaviour in SF1 too.
Best Answer
Here is a working example .app of what I think you are saying is not working for you (NOTE TO MODERATORS: I did not use a comment because they do not provide enough formatting capabilities to handle code etc).
@nevrekar_amey Please provide something similar that showcases the error case you are seeing.
controller:
helper:
css:
Or an even better approach that does not run the risk of colliding with Lightning's stewardship of the DOM elements its managing on your behalf:
Even better - this approach is also guaranteed to work in your init scenario too!