5

I have iteration in my component. Each item in iteration is table row with few inputs for text and 2 ui:inputDate.

When I have many items in array, it takes very long for component to load. In lightning inspector I can see that datepicker takes almost all CPU time. On this screenshot you can see each accumulation of call stack is for rendering each row in iteration. Green line on top is for date picker. More precise look shows that rendering component itself is very expensive operation. What is the way to improve performance of my component?

enter image description here enter image description here enter image description here

3 Answers 3

5

I used a lazy load technique. In my example I'm using my datepicker grid component, but it's the same principle:

First, define your placeholder:

<div aura:id="datePickerContainer" class="slds-p-horizontal--small slds-m-top--x-small slds-size--1-of-2 slds-medium-size--1-of-3 slds-large-size--2-of-12">
  {!v.body}
  <!-- initial date display - note, no picker present to improve performance-->
  <div aura:id="initialInput" class="slds-form-element">
    <label aura:id="initialInputDateElementLabel" class="slds-form-element__label" for="closedate">Reset Date</label>
    <div aura:id="initialInputDateElement" class="slds-form-element__control slds-input-has-icon slds-input-has-icon--right slds-float--left">
      <ui:inputText class="slds-input" label="" value="MM/dd/yyyy" click="{!c.replaceInputWithPicker}" placeholder="MM/dd/yyyy" />
    </div>
  </div>

</div>

When the user clicks, you then replace the element:

replaceInputWithPicker: function(component) {

  var datePickerContainer           = component.find('datePickerContainer');
  var initialInput                  = component.find('initialInput');
  var initialInputDateElement       = component.find('initialInputDateElement');   
  var initialInputDateElementLabel  = component.find('initialInputDateElementLabel');  

  var activity = component.get("v.activity");

  $A.util.removeClass(datePickerContainer, 'custom-hide');

  $A.createComponent(
    "c:DatePicker", {
      "aura:id": "resetDate",
      "label": "Your Date",
      "labelClass": "slds-form-element__label",
      "placeholder": "New Event Date",
      "value": activity.nextEventDate,
      "formatSpecifier": "MM/dd/yyyy",
      "style": "height: 30px; display: inline-block;",
      "dateChangeEvent": component.getReference("c.handleDateChange")
    },
    function(datePicker, status, errorMessage) {
      //Add the new button to the body array
      if (status === "SUCCESS") {

        //define custom-hide in your css - display:none;
        $A.util.addClass(initialInput, ' custom-hide ');

        datePickerContainer.set("v.body", []);

        var body = datePickerContainer.get("v.body");
        body.push(datePicker);
        datePickerContainer.set("v.body", body);

        datePicker.showCalendar();
      } else if (status === "INCOMPLETE") {
        console.log("No response from server or client is offline.")
      } else if (status === "ERROR") {
        console.log("Error: " + errorMessage);
      }
    }
  );
}

This makes a HUGE difference to speed.

Just replace my custom date picker component with your UI:InputDate. Or use mine. It's here: datepicker

Also, note the date change event method dynamic reference in the replaceInputWithPicker function - it's very useful to be able to reference existing functions and add them dynamically to your dynamic components!

Also, I don't think you need the {!body} item - I left it in there because I've forgotten if it's needed or not!!

2

This is probably not relevant, but just in case, I'll go ahead and post it as a possible answer.

I ran into an issue where I started getting "too many component" errors, and tracked down a solution here at: Intermittant error: Too many components for aura

Basically, if you're dynamically creating components and didn't specify the child component as a dependency, the system has to make some type of trip to the server for component info before it can create it, and you can run into errors if you do this too many times.

Now, it doesn't sound like you're having "too many component" errors, but if you are dynamically creating components (using $A.createComponent at least, I don't know if the same applies to things like aura:iteration), perhaps there's some performance impact that could be mitigated by referencing the child component in an aura:dependency tag. There's some interesting text about 2/3 the way down that page:

"To avoid a trip to the server for component creation in JavaScript code..."

Maybe that's related to the issues you're seeing? Anyway, thought I'd mention this just in case it's related. Good luck!

1
  • Thanks for your effort, I tried this but it didn't make noticeable changes. Please have a look at detailed chart, you can see that it takes almost all time to render component, but not to load it from server. Apr 28, 2017 at 7:23
0

Since this is controlled by framework, not us, we cannot do much about it (if not doing hacks of course).

We have new sandbox with Summer 17 release and I am able to compare performance.

In Summer 17 it takes about 5 seconds to render UI for the same data, where it took about 17 seconds in Spring 17.

3
  • 5 seconds vs 17 seconds is good... but for a user, it's still too long. I'd still use lazy loading. May 12, 2017 at 18:48
  • @CasparHarmer Thanks, but implementing lazy loading exceeds our estimates, so we stay with default solution. Maybe they will keep improving it in the future. May 12, 2017 at 20:40
  • Yes, but this is not an answer. My answer works, this is just doing nothing. May 13, 2017 at 0:52

You must log in to answer this question.

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