1

If you are creating Lightning component and enabling LockerService (Summer 16 pre-release), almost all of the functionality will be broken, specially if you are using HTML tags.

I have a very simple use case which should work but not working. Any help is appreciate.

I have one list which have 1 item. Onclick of this item, i am inserting 1 more item in this list. (Code is as given below.)

Lightning application t1.app

<aura:application>
    <ul aura:id="ul">
        <li aura:id="l1" onclick="{!c.addNewLi}"> A </li>
    </ul>
</aura:application>


t1Controller.js

({
    addNewLi: function(cmp) {
        console.log('You clicked on 1st LI.');

        // Below 2 debug log will see later
        console.warn(document.getElementById("l1"));
        console.warn(document.getElementById("l2"));

        $A.createComponents(
            [["aura:html", {"tag":"li", "body":"B", "HTMLAttributes":{"id":"l2"}}]],
            function(components, status){
                if (status === "SUCCESS") {
                    var li = components[0];
                    console.log(li);
                    var ul = cmp.find("ul");
                    var ulBody = ul.get("v.body");
                    ulBody.push(li);
                    console.log(ulBody);
                    ul.set("v.body", ulBody);
                    alert('2nd LI is added.');
                }
            }
        );
    }
})

As if you click on 1st item, no error is coming and if you check console.log(), it show 2 item but on ui level nothing is changed.

After some debugging, i modify the js controller code little bit and now 2nd li is added but now stuck on 2nd problem. Now 1st lets check the modified controller

({
    addNewLi: function(cmp) {
        console.log('You clicked on 1st LI.');

        // Below 2 debug log will see later
        console.warn(document.getElementById("l1"));
        console.warn(document.getElementById("l2"));

        $A.createComponents(
            [["aura:html", {"tag":"li", "body":"B", "HTMLAttributes":{"id":"l2"}}]],
            function(components, status){
                if (status === "SUCCESS") {
                    var li = components[0];
                    console.log(li);
                    var ul = cmp.find("ul");
                    var ulBody = [];          //ul.get("v.body");
                    ul.get("v.body").forEach(function(item, index){
                        ulBody.push(item);
                    });
                    ulBody.push(li);
                    console.log(ul);
                    ul.set("v.body", ulBody);
                    alert('2nd LI is added.');
                }
            }
        );
    }
})

Now again go to lightning app and click on 1st item and this time 2nd item will be added. But now lets talk about 2nd problem. For that see the warning message on console in browser

enter image description here

When you 1st time ckick on 1st item A, you see object and null which is correct as 2nd li is not inserted till now. But if you again click on 1st item, it show object & undefined. Now why undefined is coming as if you see the li is inserted. enter image description here

And i am in the same component and not trying to access parent, so i should get object instead of undefined. Anyone can help me on this.

2

I think we have different views about what a simple use case is - it's extremely rare that we see any code using aura:html directly like this - and I would say this is not a down the middle scenario. aura:html has special logic to handle "ownership" of elements (unlike most components it shares ownership of its internal DOM with the caller) that is getting tripped up by the dynamic creation (it should work and is a hug we will get fixed).

Is there a reason why you are not using document.createElement() directly or even better leveraging aura:iteration and value binding to handle all of this declaratively and automatically?

A bit more about why this is happening - when you use createComponent()/createComponents() you are creating an "island" component sub tree that is not truly connected to the containing component even when you set the subtree as a facet (appending to to v.body in this case). Expressions would also not resolve in this case. The component value provider is not being set so the aura:html component is "blind" and cannot see the containing component you've added it to. This is a bug in how facets are being handled today that surfaces in a number of ways not specific to LockerService.

Please open a support case with Salesforce and post the case ID here and please be sure to let our support team know that there is already a bug tracking this W-3173990

  • I can not use document.createElement() as in my actual use case when creating <li>, i am creating 1 custom component too and adding that component as child of <li>. Also 2nd reason is i don't want to modify DOM elements outside rendering cycle as given in Client-Side Rendering to the DOM aura:iteration looks not a good option for me as custom component is creating based on which item is clicked. – SFBlogForce May 31 '16 at 11:55
  • I see - BTW that "don't manipulate the DOM outside of rendering lifecycle" is meant for DOM elements that you did not create in the first place and I have already instructed our doc team to correct this overly restrictive statement. The first reason is a good one though and really even falls into the second since your mixing in LCs into the DOM subtree. I've identified the root cause (not LS but LS is being impacted) and have asked others on the Aura Framework team to jump in and help get this fixed asap. – Doug Chasman May 31 '16 at 12:31

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.