30

I have a Nav component which contains the following:

<aura:renderIf isTrue="{!v.showAllProducts}">
    <c:showAllProductsCmp/>

    <aura:set attribute="else">
        <c:showSelectedProductsCmp/>
    <aura:set>
<aura:renderIf>

On a button press, showAllProducts changes from false -> true, and true -> false.

What this does is allow a user to see all products and select them (this is done in the showAllProductsCmp component. The component simply uses <aura:iteration> to render all product objects.)

and then switch to see only the selected products with the option to unselect them (in the showSelectedProductsCmp component).

I can add and remove any/all products, and my code works as intended -- as long as there is at least one product remaining. For example, I can add 4 products, remove 3, and it works perfectly.

As soon as I remove the last product in the showSelectedProductsCmp and then try to switch back over to the showAllProductsCmp, the app crashes and I get a javascript error:

Uncaught TypeError: Cannot read property 'childNodes' of null
aura_proddebug.js:8364

This line is part of the Lightning framework. Specifically it is:

nextSibling = target.childNodes[calculatedPosition];

So the target variable is null and it crashes.

If I remove renderIf and set attribute="else" components and ALWAYS render my two custom components, everything works as it should and there are no errors -- even if I remove all products.

So I don't believe that there is anything wrong with my code, though I would be happy to be corrected :)

PS: This doesn't happen on all renderIf statements: I have quite a few of them in my code and all of them work except for this one. Which means that this is hard to reproduce, sadly.

[Edit] I guess I should note that this nav component comes after quite a few other renderIf components, so maybe Lightning struggles with more than a couple renderIf components. Another person has a similar problem to mine, and s/he also has multiple renderIf statements before the one that finally breaks. developer.salesforce.com

[Edit2] Here is how you can reproduce the error (I'm pretty sure): Create a new Lightning application and copy the following code (which contains a lot of renderIfs)

[Edit3] The previous example had an error that was my fault. I've made a new example that hopefully doesn't have an error that is my fault. :)

<aura:application >
<aura:attribute name="isEmptyArray" type="Boolean" default="false"/>
<aura:attribute name="testingArray" type="Opportunity[]"/>

<button onclick="{!c.fillArray}">Fill array</button>
<button onclick="{!c.emptyArray}">Empty Array</button>

<div>
    <aura:renderIf isTrue="{!v.testingArray.length > 0}">
        <aura:iteration items="{!v.testingArray}" var="opp">
            {!opp.name} <br/>
        </aura:iteration>
        <aura:set attribute="else">
            Array empty
        </aura:set>
    </aura:renderIf>
</div>
</aura:application>

And then copy the following code into the application controller:

({
fillArray:function(component,event,helper) {
    var tempArray = [{'sobjectType': 'Opportunity', 'name':'One'},{'sobjectType': 'Opportunity', 'name':'Two'}];
    component.set("v.testingArray", tempArray);
},
emptyArray:function(component,event,helper) {
    var emptyArray = [];
    component.set("v.testingArray", emptyArray);
}
})

Click the "fill array" button, then the "empty array" button, then the "fill array" button again. Receive the error.

  • If possible I would debug and find out where target is being defined possibly? – chrisjlee Apr 8 '15 at 20:24
  • 1
    Sure. Looks like aura_proddebug.js:8342 . The line is var target = referenceNode || component.$_marker$.parentNode; So it's still part of the Lightning framework. – Anthony F. Apr 8 '15 at 20:27
31

This is a known issue in the Framework.

We do plan to fix it, but there is a workaround and so it's not #1 on our plate over things like Performance.

Short Story

<aura:renderIf isTrue="{!v.testingArray.length > 0}">
        <SPAN>
        <aura:iteration items="{!v.testingArray}" var="opp">
            {!opp.name} <br/>
        </aura:iteration>
        </SPAN>
        <aura:set attribute="else">
            Array empty
        </aura:set>
    </aura:renderIf>

Long Story

The issue here is that some components like aura:renderIf and aura:iteration may not actually render anything. But you can come along later, change a condition and then they render.

To know where to render when it comes time to do so, we add a comment into the page. Then when we have some output, we replace the comment with the output.

But when you get a component like iteration which uses a comment, inside another component that uses a comment the framework gets confused. We replace the comment with the content of the iteration, but then renderIf loses its marker comment and you've hit the error.

Wrapping the iteration in a span causes iteration and renderIf not to share markers and things start working again.

Something we plan to fix, but the marker system is so complex we have to be careful not to break other things.

  • 4
    Why hasn't this been fixed yet? Yes there's a work around for it, but it seems like a lot of developers come across this bug with consistency (myself included). We shouldn't have to litter our components with random <span> tags in order to work around it, either. – James Loghry Sep 26 '15 at 2:50
  • 2
    Adding a span does not work for me. Furthermore if I try to move my aura:iteration outside of the aura:if, I get the error every time I change items collection instead of just the second time I change it. – Kyle Gossman Apr 10 '16 at 17:11
  • 1
    In my case it isn't nested possibly empty components that is triggering it. It is components with more that a single top level html element, running within an aura:iteration that is causing it. The child component doesn't need to contain any dynamic content, just two emptys <tr> element will do it. – andynormancx Sep 7 '16 at 14:37
  • 2
    @KrisGray - Is there a Known issue link for this bug? I would like to monitor it for status update when it is fixed. Currently adding a span is not a valid workaround in my case as well, my component is generating a table tr nodes, and span tag addition around it will break the table css :( – VarunC Oct 26 '16 at 12:18
  • 1
    I'm having the same issue as @andynormancx, with the tr elements. It's a real nightmare. Wishing you luck Kris, in your efforts to convince the framework team to make this a priority. – Jake Richter Jan 28 '17 at 18:50
10

An alternative way around this bug is to use CSS.

 <div class="{!v.showTask ? 'card' : 'card hide'}">

where:

.hide {display:none} 
5

After spring 17 release <SPAN> solution will not work.

You will receive the following error in Spring 17 Release:

This page has an error. You might just need to refresh it. render threw an error in 'markup://aura:html' [The HTML tag 'SPAN' is not allowed.] Failing descriptor: {markup://aura:html}

Workaround : Use <Div> tag instead of <SPAN> tag as in the following example:

<aura:renderIf isTrue="{!v.testingArray.length > 0}">
    <DIV>
    <aura:iteration items="{!v.testingArray}" var="opp">
        {!opp.name} <br/>
    </aura:iteration>
    </DIV> 
    <aura:set attribute="else">
        Array empty
    </aura:set>
</aura:renderIf>
  • Well that's interesting. Do you have a link to where they talk about when/why <span> isn't allowed anymore? – Anthony F. Jan 9 '17 at 18:42
  • 1
    No i haven't found anywhere regarding this. This monday when i did testing of lightning component then i am getting : This page has an error. You might just need to refresh it. render threw an error in 'markup://aura:html' [The HTML tag 'SPAN' is not allowed.] Failing descriptor: {markup://aura:html} error message is component due to spring17 release. So then i just added <Div> tag and it's worked. – Rajendra Rathore Jan 11 '17 at 13:11
  • there was a brief bug in the Spring '17 release that was causing the allowed tag validation to not handle non-lower case tags. This should no longer be failing, if it is could you let us know which instance you're on? – Luke Inman-Semerau Jan 26 '17 at 20:58
  • Here's the list of allowed tags - github.com/forcedotcom/aura/blob/master/aura-components/src/… – Luke Inman-Semerau Jan 26 '17 at 21:02
0

I seem to have found a different workaround for my particular variation on this issue.

It looks like I've managed to avoid whatever race condition it is within the framework by clearing the array I am iterating over, then "yielding" by setting the new value for the array in a setTimeout callback:

    component.set("v.visitsCurrentPage", []);
    window.setTimeout(
        $A.getCallback(function() {
            var visits = component.get("v.visits");

            if (visits.length !== 0) {
                var visitsCurrentPage = [];
                for (var index = firstItemIndex; index <= lastItemIndex; index++) {
                    visitsCurrentPage.push(visits[index]);
                }

                component.set("v.visitsCurrentPage", visitsCurrentPage);                    
            }
        }), 1
    );

(I guess technically I also need to check in there that the component is valid, though the hosting component is the top level of my app, so if it isn't I have bigger problems)

I have no idea whether this will address other instances of the issue.

I say seem to have found, as the race condition is such that in the past I've made unrelated changes to the code, that have made the issue go away for a while.

0

I'm still (v40 summer 17) seeing issues with the order of elements inside aura:iteration. I have something like:

<button>
<tbody>
    <aura:iteration....
         <c:row...
    </aura:iteration>
</tbody>

Where c:row renders 3 TRs. and the iteration grows by +1 everytime you hit the button. The rows get wacky as you press the button: let's say you press the button 2 times, you get this:

row1.1
row1.2
row2.1
row2.2
row2.3
row1.3

When you should get 1.1, 1.2, 1.3, 2.1, 2.2, 2.3

The fix for me was to put a a hidden span the end of the rowcmp

c:row

<component>
    <tr>...
    <tr>...
    <tr>...
    <span class="slds-hide" />
</component>

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.