3

I have a Lightning Community and I'm using a custom HTML template to render my pages, inside this HTML template I have a v.body where my custom components are being displayed (the ones selected from the community builder).

So the weird thing I found out is that even when I code this:

<aura:if isTrue="{!false}">
    {!v.body}
</aura:if>

The init handler of my custom components that go inside the "aura:if" is executed, although the components are not displayed on the DOM.

This is a big problem for me since I'm loading an external library on my HTML Template and rendering the {!v.body} afterScriptsLoaded, but my components keep crashing because my custom components use those libraries and the init handler keeps executing even when the isTrue statement is false. And I don't want to add my scripts on every single component inside my pages.

This seems to be a lightning bug, but I would like to be sure about this.

3 Answers 3

3

So, the specifications for aura:if explicitly state it needs an expression, however the attribute isTrue itself does say its a boolean.

Given that, I would expect your syntax to work however it looks like it may be treating it is a truthy String.

The easiest fix is to pass in an attribute like this:

<aura:attribute name="myBool" type="Boolean" default="false"/>

<aura:if isTrue="{! v.myBool }">
 ...
</aura:if>
1
  • the component is not being rendered, that means that my code is working. However, the "init" event is still being executed, that I think is the bug, Lightning is initialising the component even if the condition is false, but I guess this is because is a Page Component inside a Lightning community. Jul 20, 2018 at 14:24
2

You could load your scripts into just one component and call it using promises. Then you never need to worry about afterscriptsloaded or bad references.

You'd have a component - say called "ScriptLoader".

ScriptLoader would have these top level attributes:

<aura:attribute name="yourscriptsource" type="String" default="{!$Resource.yourscriptname}"/>
<div>
  <div class="scriptdiv" id="{!GlobalId + '_scriptdiv'}"/>
</div>
<aura:attribute name="scriptsLoaded" type="Boolean" default="false"/>

Plus a public method like this:

getYourScript: function(component) {
  return new Promise($A.getCallback(function(resolve, reject) {

    if (component.get("v.scriptsLoaded") == true) {
      resolve(window.yourscript);
    } 
    else {

      // Create script element and set attributes
      var script = document.createElement('script');
      script.type = 'text/javascript';
      script.async = true;
      //resource reference to your script 
      script.src = component.get("v.yourscriptsource");

      var el = document.getElementsByClassName('scriptdiv')[0];
      el.parentNode.insertBefore(script, el);

      // Resolve the promise once the script is loaded
      script.addEventListener('load', () => {
        component.set("v.scriptsLoaded", true);
        resolve(window.yourscript);
      });

      // Catch any errors while loading the script
      script.addEventListener('error', () => {
        reject('yourscript failed to load');
      });
    }

  }))
},

Assuming you have defined this method as an aura:method on the component, you can then call it like this:

var scriptLoader = component.find('scriptLoader');
scriptLoader.getYourScript()
  .then(
    yourscript => {
      yourscript.something()
    }
  )
  .then(
    (someresult) => {
      //do something else
    }
  )
2
  • Thanks for your answer! I guess that would work if the caller component is the parent component, but this is not my case, and I would prefer not adding this 'ScriptLoader' component everywhere or having to add any logic inside every component that needs the script. Jul 14, 2018 at 11:31
  • Yes, if you were to use the component only for loading scripts, then you mayaswell just use the built in loader. However, I actually use this component for most DML and SOQL calls (when I'm not using a recorddata component), so it becomes quite useful. Jul 14, 2018 at 19:14
0

You can always try to replace aura:if with aura:renderIf it is little bit different and does not render any content until variable changes. Salesforce states it is slower, but I had multiple issues with aura:if that were simply resolved by using aura:renderIf

4
  • 1
    aura:renderIf is deprecated, so you are taking a pretty big risk that this function will entirely disappear. Jul 9, 2018 at 7:43
  • I know it is, but aura:if is broken in some cases.
    – Paul
    Jul 9, 2018 at 8:46
  • 1
    @Paul which cases? I've been using it quite reliably
    – tsalb
    Jul 9, 2018 at 15:57
  • If you could show us some cases of it not working (maybe in a new linked ticket) we might be able to debug for you... I'm pretty sure aura:if is solid Jul 9, 2018 at 18:35

You must log in to answer this question.

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