6

I am having an issue when using NiceScroll (GIT Hub) when locker service is enabled.

If the locker is turned off, it work's fine.

Code:-

Component:

<ltng:require scripts="{!join(',',
     $Resource.namespace__StaticResourceName + '/scripts/jQuery_V1.js',
     $Resource.namespace__StaticResourceName + '/scripts/nicescroll.js'
     )}" afterScriptsLoaded="{!c.scriptsLoaded}" />

<aura:attribute name="isResourcesLoaded" type="Boolean" default="false"/>

<div class="slds-form-element__control textarea-wrapper">
    <ui:inputTextArea value="{!v.newVF.namespace__Notes__c}" aura:id="editModeScrollBarY" maxlength="255" 
    class="slds-textarea scrollbar-outer"/>
</div>

Controller:

scriptsLoaded : function(component, event, helper) {
        component.set("v.isResourcesLoaded", true);
}

Helper:

    addScroll : function(component){
       if(component.isValid() && component.get("v.isResourcesLoaded")){
            $(".scrollbar-outer").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);
    }   
})

isResourcesLoaded is a Boolean attribuite which I'm setting as true in afterScriptsLoaded (to make sure that the external scipts uploaded as static resources have loaded).

Also, I'm calling the addScroll function from the renderer to make sure that the DOM elements have also loaded successfully before adding scroll to a DOM element.

The above code works fine when locker service is not active.

It would be very helpful if anyone can provide a solution to solve this issue. Also, is there any alternative to add scroll to a textarea with LS active for Salesforce-1?

7
+50

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. :-(

nicescroll in text area

P.S: I observe the same behaviour in SF1 too.

  • Thank you so much @Praveen. Can you please tell me the workaround to populate value from the backend if it's normal <textarea>? If it's ui:inputTextArea, I can do the same like <ui:inputTextArea value="{!v.newVF.namespace__Notes__c}" />. I sincerely apologise for not including the same in the question. – SE_User Sep 19 '16 at 10:59
  • @SE_User I have updated the answer check it out. – Praveen Sep 19 '16 at 11:26
  • Hi @Praveen, I tried with your updated code (with the jQuery 2.2.4 and nicescrol v3.6.8). But it's not working (It's not throwing any error, though). The scroll is not being applied to the textarea. All the functions are being fired too. Can you please tell me if you've done any modification to the nicescroll.js file to make it work? – SE_User Sep 20 '16 at 9:17
  • @SE_User I didn't modify nicescroll.js.I confirmed the behaviour with locker off using your code(since you mentioned it works) with the above answer with locker on, it works as expected.I could see that native scroll is replaced with very thin scroll bar which appears within the textarea only when there is no typing done. – Praveen Sep 20 '16 at 17:52
  • 1
    @SE_User I have updated the answer.Sadly with locker on scrolling did not work.I'm afraid you have to create a case with sf support regarding this. – Praveen Sep 21 '16 at 17:54
1

Interacted about this on "Lightning Components - Trailblazers" group. Cross posting my response here.

Problem is that aura:id="editModeScrollBarY" aura:id maps to to ui:inputTextArea. As that component is in a different namespace, your component doesn't have access to the dom elements owned by it. Hence, you are not allowed to call getElement(). You could workaround it by having a component in your namespace render the elements you'd like to get your hands on.

You can only get your hands on an element you own. For example if instead of using ui:inputTextArea, you had used raw textArea html-component, you should have been able to call getElement on it.

  • Thank you @esalman. But then Unable to add custom scroll due to “component/namespace encapsulation” when Locker Service is active Can you please take a look at it then? – SE_User Dec 10 '16 at 7:10
  • @SE_User thats basically the same error as this one (you not having access to elements rendered by a component not in your namespace). – Emad Salman Dec 11 '16 at 8:32
  • Have you tried using textArea directly (e.g. <textArea aura:id="tId" ..> and then cmp.find("tId").getElement() ) as in that case you would have access to the element it maps to. – Emad Salman Dec 11 '16 at 8:35
  • Yes, @esalman I've accepted that in the question itself and has even referenced Doug Chasman's answer too. But can you please provide a solution for the issue?? So, you're saying that there is no scroll functionality by default in ui:inputTextArea as well as the lightning:textarea and we should not use that and should always depend on external scroll plugins which throws error when locker Service is activated? It would be very helpful if you could provide a workaround. Thank you. – SE_User Dec 12 '16 at 5:31
  • This is not accurate. We intentionally block textarea cols and rows in lightning:textarea because you can achieve the same using CSS in a way that works well in all different form-factors. And the native scroll on textarea elements should work just fine. – Caridy Patiño Dec 13 '16 at 20:45

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.