4

Recently I got a very weird issue with aura:iteration and don't know how to solve it yet.

If I sort my list of element to ascending order and delete some element from the list then if I try to sort my list of elements once again I got the following error:

rerender threw an error in 'aura:iteration' [Failed to execute 'insertBefore' on 'Node': The new child element contains the parent.] Failing descriptor: {aura:iteration}

I found similar question Problem re-ordering table rows in a Lightning Component but in my case the DOM is clear. Here is the simplified example that reproduces my issue (you can clone it from here sample issue:

<!-- Main.cmp -->
<aura:component>
<aura:attribute name="items" type="List" />
<aura:attribute name="sortAsc" type="Boolean" default="{!false}" />

<aura:handler name="init" value="{!this}" action="{!c.init}" />

<div class="main">
    <aura:iteration items="{!v.items}" var="item">
        <div>
            <c:Child item="{!item}" />
        </div>
    </aura:iteration>
</div>

<lightning:button label="Sort Items" variant="brand" onclick="{!c.sortItems}" />
<lightning:button label="Delete Item" variant="brand" onclick="{!c.deleteItem}" />
</aura:component>

MainController.js

<!-- MainController.js -->
({
init: function(component, event, helper) {
    var items = [
        {attr1: 1, attr2: '1', sortAsc: false},
        {attr1: 2, attr2: '2', sortAsc: false},
        {attr1: 3, attr2: '3', sortAsc: false},
        {attr1: 4, attr2: '4', sortAsc: false},
        {attr1: 5, attr2: '5', sortAsc: false},
    ];
    component.set('v.items', items);
},

sortItems: function(component, event, helper) {
    var items = component.get('v.items');
    var sortAsc = !component.get('v.sortAsc');
    component.set('v.sortAsc', sortAsc);
    items.sort(helper.sortFunction(sortAsc));
    component.set('v.items', items);
},

deleteItem: function(component, event, helper) {
    var items = component.get('v.items');
    items.splice(0, 1);
    component.set('v.items', items);
}
});

MainHelper.js

<!-- MainHelper.js -->
({
sortFunction: function(sortAsc, index) {
    return function(a,b) {
        if ( sortAsc ) {
            return a.attr1 - b.attr1;
        } else {
            return b.attr1 - a.attr1;
        }

    }
}
});

Child.cmp

<!-- Child.cmp -->
<aura:component>
<aura:attribute name="item" type="Object" />

{!v.item.attr2}
</aura:component>

Test.app

<aura:application extends="force:slds">
<c:Main />
</aura:application>

To reproduce this issue open Test.app click on "Sort Items" button 2 times. Then click on "Delete Item" and after click on "Sort Items" button 2 times again and you'll see the error.

Is it a Lightning Framework bug. Are there any workarounds?

2 Answers 2

3

Fortuitous timing. We think this was just addressed in a change in framework last week.

Change here https://github.com/forcedotcom/aura/commit/b76df7cc31e9bb69425f0a41d4f748ceb6978631

1
  • Any timeframe when this fix will be merged into Lightning / deployed to orgs? Will it be addressed in Summer 18? (Safe Harbor)
    – steals
    Apr 2, 2018 at 19:43
7

It definitely seems like a bug in the framework. I don't have any explanation as to why it happens, but I have found it helpful in these cases to "reset" the iteration items before setting them again.

In other words, your sortItems function would become

sortItems: function(component, event, helper) {
    var items = component.get('v.items');
    var sortAsc = !component.get('v.sortAsc');
    component.set('v.sortAsc', sortAsc);
    items.sort(helper.sortFunction(sortAsc));
    component.set('v.items', []);
    component.set('v.items', items);
},

I tested your code and couldn't get the error to occur when I did this.

1
  • Thanks for the workaround. It fixes the issue, but performance becomes quite slow in real application. Accepted Kris's answer as he confirmed it's the issue in the framework.
    – steals
    Apr 2, 2018 at 19:49

You must log in to answer this question.

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