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)

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

1 Answer 1

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

11
  • 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. Commented Nov 16, 2016 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. Commented Nov 16, 2016 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/… Commented Nov 16, 2016 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. Commented Nov 16, 2016 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. Commented Nov 16, 2016 at 20:01

You must log in to answer this question.

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