8

This question already has an answer here:

Given this gist, you'll see that there's three revisions. The first revision dealt with stray tab characters, but the second revision came about because of an apparent bug. When clicking on the headers to change the sort order, changing between the first and second columns would occasionally result in the following error:

This page has an error. You might just need to refresh it.

rerender threw an error in 'markup://aura:if' [Cannot read property 'childNodes' of null] Failing descriptor: {markup://aura:if}

What follows is the broken version of this app.

Basically, I need to know if nested aura:if is supported, and if so, if there's anything I need to not trigger this behavior. Otherwise, if this is a bug, is there somewhere I can report this to?


pagingSortingDemo.app

<aura:application extends="force:slds" controller="PagingSortingDemo">
    <aura:attribute type="Account[]"
                    name="allAccounts" />
    <aura:attribute type="Account[]"
                    name="currentList" />
    <aura:attribute type="Integer"
                    name="pageNumber" 
                    default="1" />
    <aura:attribute type="Integer"
                    name="maxPage" 
                    default="1" />
    <aura:attribute type="String"
                    name="sortField" />
    <aura:attribute type="Boolean"
                    name="sortAsc" />
    <aura:handler name="init"
                  value="{!this}"
                  action="{!c.doInit}" />
    <table class="slds-table slds-table--bordered slds-table--cell-buffer">
        <thead>
            <tr class="slds-text-title--caps">
                <th scope="col">
                    <div onclick="{!c.sortByName}"
                         class="slds-truncate"
                         title="Account Name">
                        Account Name
                        <aura:if isTrue="{!v.sortField=='Name'}">
                            <aura:if isTrue="{!v.sortAsc}">
                                &#8593;
                                <aura:set attribute="else">
                                    &#8595;
                                </aura:set>
                            </aura:if>
                        </aura:if>
                    </div>
                </th>
                <th scope="col">
                    <div onclick="{!c.sortByIndustry}"
                         class="slds-truncate"
                         title="Account Name">
                        Industry
                        <aura:if isTrue="{!v.sortField=='Industry'}">
                            <aura:if isTrue="{!v.sortAsc}">
                                &#8593;
                                <aura:set attribute="else">
                                    &#8595;
                                </aura:set>
                            </aura:if>
                        </aura:if>
                    </div>
                </th>
                <th scope="col">
                    <div onclick="{!c.sortByAnnualRevenue}"
                         class="slds-truncate"
                         title="Account Name">
                        Annual Revenue
                        <aura:if isTrue="{!v.sortField=='AnnualRevenue'}">
                            <aura:if isTrue="{!v.sortAsc}">
                                &#8593;
                                <aura:set attribute="else">
                                    &#8595;
                                </aura:set>
                            </aura:if>
                        </aura:if>
                    </div>
                </th>
            </tr>
        </thead>
        <tbody>
            <aura:iteration items="{!v.currentList}"
                            var="record">
                <tr>
                    <th data-label="Account Name">
                        <div class="slds-truncate" title="{!record.Name}">
                            {!record.Name}
                        </div>
                    </th>
                    <th data-label="Industry">
                        <div class="slds-truncate" title="{!record.Industry}">
                            {!record.Industry}
                        </div>
                    </th>
                    <th data-label="Annual Revenue">
                        <div class="slds-truncate" title="{!record.AnnualRevenue}">
                            {!record.AnnualRevenue}
                        </div>
                    </th>
                </tr>
            </aura:iteration>
        </tbody>
    </table>
    <div class="slds-button-group" role="group">
        <button onclick="{!c.firstPage}"
                class="slds-button slds-button--neutral">
            First
        </button>
        <button onclick="{!c.prevPage}"
                class="slds-button slds-button--neutral">
            Prev
        </button>
        <button class="slds-button slds-button--neutral">
            {!v.pageNumber}
            /
            {!v.maxPage}
        </button>
        <button onclick="{!c.nextPage}"
                class="slds-button slds-button--neutral">
            Next
        </button>
        <button onclick="{!c.lastPage}"
                class="slds-button slds-button--neutral">
            Last
        </button>
    </div>
</aura:application>

pagingSortingDemoController.js

({
    doInit: function(component, event, helper) {
        var action = component.get("c.getAccounts");
        action.setCallback(this, function(result) {
            var records = result.getReturnValue();
            component.set("v.allAccounts", records);
            component.set("v.maxPage", Math.floor((records.length+9)/10));
            helper.sortBy(component, "Name");
        });
        $A.enqueueAction(action);
    },
    sortByName: function(component, event, helper) {
        helper.sortBy(component, "Name");
    },
    sortByIndustry: function(component, event, helper) {
        helper.sortBy(component, "Industry");
    },
    sortByAnnualRevenue: function(component, event, helper) {
        helper.sortBy(component, "AnnualRevenue");
    },
    firstPage: function(component, event, helper) {
        component.set("v.pageNumber", 1);
        helper.renderPage(component);
    },
    prevPage: function(component, event, helper) {
        var pageNum = component.get("v.pageNumber");
        if(pageNum > 1) {
            component.set("v.pageNumber", pageNum - 1);
            helper.renderPage(component);
        }
    },
    nextPage: function(component, event, helper) {
        var pageNum = component.get("v.pageNumber"),
            records = component.get("v.allAccounts");
        if(pageNum < (records.length+9)/10) {
            component.set("v.pageNumber", pageNum + 1);
            helper.renderPage(component);
        }
    },
    lastPage: function(component, event, helper) {
        var pageNum = component.get("v.pageNumber"),
            records = component.get("v.allAccounts");
        if(pageNum != (records.length+9)/10) {
            component.set("v.pageNumber", (records.length+9)/10);
            helper.renderPage(component);
        }
    }
})

pagingSortingDemoHelper.js

({
    sortBy: function(component, field) {
        var sortAsc = component.get("v.sortAsc"),
            sortField = component.get("v.sortField"),
            records = component.get("v.allAccounts");
        sortAsc = sortField != field || !sortAsc;
        records.sort(function(a,b){
            var t1 = a[field] == b[field],
                t2 = (!a[field] && b[field]) || (a[field] < b[field]);
            return t1? 0: (sortAsc?-1:1)*(t2?1:-1);
        });
        component.set("v.sortAsc", sortAsc);
        component.set("v.sortField", field);
        component.set("v.allAccounts", records);
        this.renderPage(component);
    },
    renderPage: function(component) {
        var records = component.get("v.allAccounts"),
            pageNumber = component.get("v.pageNumber"),
            pageRecords = records.slice((pageNumber-1)*10, pageNumber*10);
        component.set("v.currentList", pageRecords);
    }
})

PagingSortingDemo.cls

global class PagingSortingDemo {
    @AuraEnabled global static Account[] getAccounts() {
        return [SELECT Name, Industry, AnnualRevenue FROM Account LIMIT 1000];
    }
}

The following version of the app avoids the bug. No changes were made to the controller, helper, or Apex Code.

pagingSortingDemo.app

<aura:application extends="force:slds" controller="PagingSortingDemo">
  <aura:attribute type="Account[]"
                  name="allAccounts" />
  <aura:attribute type="Account[]"
                  name="currentList" />
  <aura:attribute type="Integer"
                  name="pageNumber" 
                  default="1" />
  <aura:attribute type="Integer"
                  name="maxPage" 
                  default="1" />
  <aura:attribute type="String"
                  name="sortField" />
  <aura:attribute type="Boolean"
                  name="sortAsc" />
  <aura:handler name="init"
                value="{!this}"
                action="{!c.doInit}" />
  <table class="slds-table slds-table--bordered slds-table--cell-buffer">
    <thead>
      <tr class="slds-text-title--caps">
        <th scope="col">
          <div onclick="{!c.sortByName}"
               class="slds-truncate"
               title="Account Name">
            Account Name
            <aura:if isTrue="{!v.sortField=='Name'}">
              {!v.sortAsc?'&#8593;':'&#8595;'}
            </aura:if>
          </div>
        </th>
        <th scope="col">
          <div onclick="{!c.sortByIndustry}"
               class="slds-truncate"
               title="Account Name">
            Industry
            <aura:if isTrue="{!v.sortField=='Industry'}">
              {!v.sortAsc?'&#8593;':'&#8595;'}
            </aura:if>
          </div>
        </th>
        <th scope="col">
          <div onclick="{!c.sortByAnnualRevenue}"
               class="slds-truncate"
               title="Account Name">
            Annual Revenue
            <aura:if isTrue="{!v.sortField=='AnnualRevenue'}">
              {!v.sortAsc?'&#8593;':'&#8595;'}
            </aura:if>
          </div>
        </th>
      </tr>
    </thead>
    <tbody>
      <aura:iteration items="{!v.currentList}"
                      var="record">
        <tr>
          <th data-label="Account Name">
            <div class="slds-truncate" title="{!record.Name}">
              {!record.Name}
            </div>
          </th>
          <th data-label="Industry">
            <div class="slds-truncate" title="{!record.Industry}">
              {!record.Industry}
            </div>
          </th>
          <th data-label="Annual Revenue">
            <div class="slds-truncate" title="{!record.AnnualRevenue}">
              {!record.AnnualRevenue}
            </div>
          </th>
        </tr>
      </aura:iteration>
    </tbody>
  </table>
  <div class="slds-button-group" role="group">
    <button onclick="{!c.firstPage}"
            class="slds-button slds-button--neutral">
      First
    </button>
    <button onclick="{!c.prevPage}"
            class="slds-button slds-button--neutral">
      Prev
    </button>
    <button class="slds-button slds-button--neutral">
      {!v.pageNumber} / {!v.maxPage}
    </button>
    <button onclick="{!c.nextPage}"
            class="slds-button slds-button--neutral">
      Next
    </button>
    <button onclick="{!c.lastPage}"
            class="slds-button slds-button--neutral">
      Last
    </button>
  </div>
</aura:application>

marked as duplicate by sfdcfox, Community Nov 28 '16 at 13:33

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 3
    It does not really answer but to workaround you can use `<aura:if isTrue="{!(v.sortField=='Name' && v.sortAsc}">. Or {!and(v.sortField=='Name',v.sortAsc). Seems like a bug to me. – Ashwani Nov 25 '16 at 4:59
  • @Ashwani Yes, I found a similar workaround, but I'm thinking about situations where this apparent limitation would cause a drastic increase in the amount of code that needs to be duplicated. – sfdcfox Nov 25 '16 at 15:08
  • Nested aura:ifs are definitely supported and are rather common, albeit expensive. I'm guessing there's an access issue in your code. – citizen conn Nov 25 '16 at 16:51
3

See my more detailed answer here Lightning: Bug in Lightning framework when using aura:renderIf?

The framework does support nested ifs, it's simply that it has a bug you appear to be running into.

Surround the content of the second if with a div if possible.

You could also make the first child after the if a div (style="display:none" even works).

  • 1
    Thanks. I've redirected this answer to the full answer that explains what's going on by closing as duplicate. Now that I know what's causing it, and the workaround, I can use that in future works. I had no idea so much stuff was going on under the hood! – sfdcfox Nov 28 '16 at 13:34

Not the answer you're looking for? Browse other questions tagged or ask your own question.