3

I have the following component in my dev org:

<aura:component implements='forceCommunity:availableForAllPageTypes' access='global'>
    <div aura:id='myDiv' id='myDiv' access='global'>Hello World!</div>
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" /> 
</aura:component>

with the following controller:

({
    doInit : function(component, event, helper) {
        var content = component.find('myDiv');
        debugger; 
    }
})

EDIT: and the following renderer:

({
  afterRender: function(component, helper) {
        var ret = component.superAfterRender();
        var content = component.find('myDiv');
        debugger;      

        return ret;
  },
  render: function(component, helper) {
        var ret = component.superRender();
        var content = component.find('myDiv');
        debugger;

        return ret;
  },
  rerender: function(component, helper) {
        var ret = component.superRerender();
        var content = component.find('myDiv');
        debugger;

        return ret;
  },
})

When I activate locker service, the content of my content variable in my controller is a

"SecureComponentRef: markup://aura:html {8:68;a} {myDiv}{ key: {"namespace":"myNamespace"} }"

On a SecureComponentRef there isn't any getElement() or getElements methods to access the DOM (to then bind some script).

I've tried the same function in different events, but I always get the Ref.

Being in the same namespace (aka the same component), why can't I access the SecureComponent instead?

(@Doug seems to say I should be able here: Why do some lightning components have more methods / properties than others)

  • 1
    just guessing, is it maybe because you have aura:id as well as id for the div? – Rao Nov 15 '16 at 21:20
  • @Rao, already tried all possibilities (Auraid only, AuraId and id, and Id only) – Marc-Antoine Veilleux Nov 15 '16 at 21:24
5

This is because you are trying to access the DOM elements in the init handler before they have been rendered. Even if you use the native document.getElementById('myDiv') call inside the init handler with LockerService disabled, you'll get null back.

If you move your find('myDiv') call to a button click handler it will return the correct SecureComponent object.

Also, the access="global" on a div element won't do anything useful. That property is specifically for Aura types (components, attributes, etc).

Edit (Nov. 16):

From Doug's comment, for situations similar to this you may want to explore custom renderers. Handle with care though.

https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/js_renderers.htm?search_text=renderer

  • 1
    Like Trevor said this is working as designed and actually eliminates one of the most common timing/confusion bugs right from the docs: "Use the init event to initialize a component or fire an event after component construction but before rendering." Calling .getElement() inside of init event handlers generates some of the greatest volume of questions about why it does not work or sometimes works (its never supposed to work BTW). Locker is not just about security but also about clearing the minefield. – Doug Chasman Nov 16 '16 at 0:58
  • 1
    ... Another example is we will be eliminating the need to know about $A.getCallback() - something that nobody gets correct the first time. developer.salesforce.com/docs/atlas.en-us.lightning.meta/… is an easy one to get wrong. – Doug Chasman Nov 16 '16 at 1:02
  • 2
    Another thing to look into if you are going to be working directly with the DOM is Renderers - most often a solid choice for the location of code that relies on the existence of DOM elements. developer.salesforce.com/docs/atlas.en-us.lightning.meta/… – Doug Chasman Nov 16 '16 at 1:04
  • Thanks for the quick answer. But I did try to bind myself on multiple events in the renderer. I've edited the post - I still get a SecureComponentRef in the afterRender in a custom renderer. – Marc-Antoine Veilleux Nov 16 '16 at 19:58
  • By the way, I did try document.getElementById('myDiv') on the afterRender and I have access to the DOM. Should'nt component.find() also work? The element is rendered at this point. – Marc-Antoine Veilleux Nov 16 '16 at 20:01

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.