2

Trying to add a style overflow: hidden to the body element of a component from the controller in v40.0

I have been unsuccessful with anything other than:

document.body.style.overflow = 'hidden'

Is there a "lightning" way to do this?

I have tried all variations of component.get / find with and without getElement and with an without {!v.body} in the markup and I cannot seem to find the correct combination to do it other than the document.body way.

Ok. Let me add a completely reproducible example

VF Page

<apex:page id="myTestPage" showHeader="false" sideBar="false" standardStylesheets="false">


    <apex:includeLightning/>
    <apex:slds />


    <script>

        $Lightning.use("c:myTestApp", function () {
            $Lightning.createComponent(
                    "c:myTestComp",
                    {},
                    "component_content",
                    function (cmp) {
                        var loadingDivElt = document.getElementById("loader");
                        loadingDivElt.style.display = 'none';
                    });
        });

    </script>

    <div class="slds-scoped">
        <div id="loader" class="slds-grid slds-grid--frame">
            <div class="slds-spinner_container">
                <div class="slds-spinner slds-spinner--brand slds-spinner--large" role="alert">
                    <span class="slds-assistive-text">Loading</span>
                    <div class="slds-spinner__dot-a"></div>
                    <div class="slds-spinner__dot-b"></div>
                </div>
            </div>
        </div>
    </div>

    <div id="component_content">
    </div>
</apex:page>

Lightning App

<aura:application description="myTestApp" extends="ltng:outApp">
    <aura:dependency resource="c:myTestComp"/>
</aura:application>

Lightning Component

<aura:component description="myTestComp">
    <div class="slds-grid slds-grid_frame" style="height: 3000px">
        <div class="slds-grid">
            <div class="slds-size_1-of-1">
                <lightning:button label="Show modal (Body still scrolls)" onclick="{!c.showSupportModalNoWork}" variant="brand"/>
                <lightning:button label="Show modal (Body does not scrolls)" onclick="{!c.showSupportModal}" variant="brand"/>
            </div>
        </div>
        <!-- Support Case Modal -->
        <div class="submit-case">
            <section aura:id="submit-case-modal" role="dialog" tabindex="-1" aria-labelledby="submit-case-heading-01"
                     aria-modal="true"
                     aria-describedby="submit-case-content-id-1" class="slds-modal">
                <div class="slds-modal__container">
                    <header class="slds-modal__header">
                        <button class="slds-button slds-button_icon slds-modal__close slds-button_icon-inverse"
                                onclick="{!c.hideSupportModal}"
                                title="Close">
                            <lightning:icon iconName="utility:close" variant="bare" size="medium"/>
                        </button>

                        <h2 id="submit-case-heading-01" class="slds-text-heading_medium slds-hyphenate">
                            ContactSupport
                        </h2>
                    </header>
                    <div class="slds-modal__content slds-p-around_medium" id="submit-case-content-id-1">
                        Some text
                    </div>
                    <footer class="slds-modal__footer">
                        <button class="slds-button slds-button_neutral" onclick="{!c.hideSupportModal}">Cancel</button>
                        <button class="slds-button slds-button_brand">Send</button>
                    </footer>
                </div>
            </section>
            <div aura:id="modal-background" class="slds-backdrop"></div>
        </div>
    </div>

</aura:component>

Component CSS (Even though class is never applied)

.THIS.myClass, .THIS .myClass, .THIS body.myClass {
    overflow: hidden;
}

Lightning Controller

showSupportModalNoWork: function(component,event,helper){
    $A.util.addClass(component.find("body"),"myClass"); //Inspect the DOM and you will see that the body does not have the class applied
    $A.util.addClass(document.body,'myClass'); //Inspect the DOM and you will see that the body does not have the class applied

    $A.util.addClass(component.find("submit-case-modal"),"slds-fade-in-open");
    $A.util.addClass(component.find("modal-background"),"slds-backdrop_open");
},
showSupportModal: function(component,event,helper){
    document.body.style.overflow = 'hidden';
    $A.util.addClass(component.find("submit-case-modal"),"slds-fade-in-open");
    $A.util.addClass(component.find("modal-background"),"slds-backdrop_open");
},
hideSupportModal: function(component,event,helper){
    document.body.style.overflow = null;
    $A.util.removeClass(component.find("submit-case-modal"),"slds-fade-in-open");
    $A.util.removeClass(component.find("modal-background"),"slds-backdrop_open");

}

I have tried adding the <body> tag and the {!v.body} and several variation of component.[find | get] and the css never gets applied to the body, with and without getElement() which throws an error

The only way I could get it to work is by using document.body and it does not feel right and was curious if there is a way to do it using lightning methods or whatever.

Note: I did not apply the style here

4
  • does your body have an aura:id ?
    – glls
    Commented Sep 13, 2017 at 19:00
  • I don't have an actual body element in the markup. Trying to get the default body.
    – Eric
    Commented Sep 13, 2017 at 19:01
  • Lightning discourages the use of direct styles. You should always use a class.
    – sfdcfox
    Commented Sep 13, 2017 at 19:34
  • @sfdcfox I tried .THIS and .THIS body to no avail. Also cannot get A.util.addClass to work with body and actually add the class. component.get("[v.body | body] does not add the class to body and getElement always throws an error
    – Eric
    Commented Sep 13, 2017 at 19:35

2 Answers 2

3

Access to document.body is apparently legal (see the Locker API Viewer under Secure Document), and it is indeed the only way you're going to get access to the main body. component.find() only works for elements inside the component, not outside of it.

I'm pretty sure that this access was intended for use cases like yours, where you're trying to do stuff outside of the Lightning context entirely. You can't, for example, use document.body to gain access to another component that you ordinarily could not via querySelector (it calls SecureElement.secureQuerySelector instead), but access to the surrounding environment allows manipulation of elements that aren't directly protected by Locker Service.

6
  • Thanks for that. Always learn something new from you. Thanks for the link too. Will try and digest some of it and put it to use
    – Eric
    Commented Sep 14, 2017 at 0:50
  • @sfdcfox code link you shared is broken and not working anymore. Is there any alternative repo or related one?
    – Mahmood
    Commented Mar 8, 2018 at 12:50
  • 2
    @Mahmood The file that was referenced was moved. I can try to find it, since it should be in the repo somewhere, but it doesn't really matter; clearly something's changed since then. You might ask a new question with your specific issue.
    – sfdcfox
    Commented Mar 8, 2018 at 15:35
  • @sfdcfox any luck fixing the broken link? :)
    – Robs
    Commented Feb 7, 2019 at 17:26
  • the attached link is broken. Commented Apr 22, 2019 at 7:32
1

Lightning way to do that could be selecting the component with component.find() function. Then adding custom CSS class to this component.

Component

<aura:component>
    <c:customComponent aura:id="myCustomComponent" />
</aura:component>

Controller

onSomeAction: function(component) {
    var myCustomComponent = component.find('myCustomComponent');
    $A.util.addClass(myCustomComponent, 'my-overflow');
}

CSS Source

.THIS .my-overflow {
    overflow: hidden;
}
2
  • Unfortunately this does not help as I need to apply the styles directly to the <body> tag dynamically and it is the topmost component
    – Eric
    Commented Sep 13, 2017 at 19:40
  • 1
    @Eric Got it. I don't know about any other way than accessing the body directly. Commented Sep 13, 2017 at 19:50

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .