[SalesForce] Lightning Component works on Sandbox but not on Production

Custom Lightning Component used in a Visualforce page (because not everybody is ready to change to LEX) is visible and works in our sandbox instance just fine. However, when deployed to production the component doesn't work as expected.

The component is a wizard to help users process some records (custom objects) in a quicker way. The first page is a form that the user must specify information regarding a volume (weight and dimensions) and the next one would list the custom objects associated with the object whose Id was passed by the URL (I'm getting the Id using {!$CurrentPage.parameters.Id} on the component script initializer on the Visualforce page).

This part of the wizard has some code to convert the weight and dimensions from the US-system to the metric system ("lbs" to "kg" and "in" to "cm"). This stops working on production, and the component doesn't throw errors (not even that black letters on the bottom of the page).

Like most wizards, the component offers some buttons on the lower side of the page to allow the user to navigate between steps. The user can navigate "forward" by increasing the value in a variable called v.page and can go back by subtracting the value too. In production, the user can't go back but can go forward.

Issue 1 Code

The conversion code looks like this:

...
convert : function (component, event, helper) {
  var volumes = component.get('v.volumes')
  volumes.forEach(function (volume) {

    // weight
    if (volume.lbs_weight !== undefined && volume.lbs_weight !== volume.prev_lbs) {
      volume.kg_weight = helper.fromLbsToKg(volume.lbs_weight)
    }
    if (volume.kg_weight !== undefined && volume.kg_weight !== volume.prev_kg) {
      volume.lbs_weight = helper.fromKgToLbs(volume.kg_weight)
    }

    // width
    if (volume.in_width !== undefined && volume.in_width !== volume.prev_in_width) {
      volume.cm_width = helper.fromInToCm(volume.in_width)
    }
    if (volume.cm_width !== undefined && volume.cm_width !== volume.prev_cm_width) {
      volume.in_width = helper.fromCmToIn(volume.cm_width)
    }

    // height
    if (volume.in_height !== undefined && volume.in_height !== volume.prev_in_height) {
      volume.cm_height = helper.fromInToCm(volume.in_height)
    }
    if (volume.cm_height !== undefined && volume.cm_height !== volume.prev_cm_height) {
      volume.in_height = helper.fromCmToIn(volume.cm_height)
    }

    // length
    if (volume.in_length !== undefined && volume.in_length !== volume.prev_in_length) {
      volume.cm_length = helper.fromInToCm(volume.in_length)
    }
    if (volume.cm_length !== undefined && volume.cm_length !== volume.prev_cm_length) {
      volume.in_length = helper.fromCmToIn(volume.cm_length)
    }

    volume.prev_kg = volume.Weight__c
    volume.prev_lbs = volume.lbs_weight

    volume.prev_cm_height = volume.cm_height
    volume.prev_cm_width = volume.cm_width
    volume.prev_cm_length = volume.cm_length

    volume.prev_in_height = volume.in_height
    volume.prev_in_width = volume.in_width
    volume.prev_in_length = volume.in_length

    volume.Width__c = volume.cm_width
    volume.Height__c = volume.cm_height
    volume.Length__c = volume.cm_length
    volume.Weight__c = volume.kg_weight
  })
  component.set('v.volumes', volumes)
},
...

All these attributes are used to imitate an AngularJS on-blur expression. When user types on the weight input for kilograms, this code runs and calculates the pounce value.

<lightning:input type="number" min="0" name="number" step="0.001" label="Weight (kg)" value="{!vol.kg_weight}" class="slds-m-around--small" onblur="{!c.convert}"/>

Update on Issue 1's code

The conversion seems to be working fine, as I've checked on the console:

console shows attributes correctly

However the value isn't displayed on the page's input as it would be expected.

Sandbox:

sandbox

Production:

production

Update on Issue 1 (12 May 2017):

It seems that the only logical explanation for this error is a bug with the lightning:input tag on production instances or instances on Spring 17. The component is still marked as in beta too. So I ended rewriting this page with AngularJS and Visualforce Remoting for now.

Issue 2 Code (solved for now, and fixed on Summer 17)

The below issue was solved (see my comment on Caspar Harmer's post):

The button to "go back" looks like this:

...
previous : function (component, event, helper) {
  var page = component.get('v.page')
  component.set('v.page', page - 1)

  if (page - 1 === 0) {
    // erase items displayed on a list that is
    // generated when user advances to the next
    // step
    component.set('v.invoiceitems', [])
  }
}
...

v.invoiceitems is an attribute that is used to store a list of custom objects that is displayed on the second page (it is a list of records retrieved from the database). The database retrieval doesn't work either, but the component does not throw errors. This list is not used when the v.page is 0 (the first step in the wizard). When it is used (step 1) it is not empty and if it is, it is only used on an aura:iteration loop, so the list would just appear as empty on the page.

Finally, the error displayed on the page when the user tries to "go back" on production is:

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}

Both problems are particularly interesting because they don't seem to be caused by field level security issues. And it is not like I, as a sysadmin, don't have access to the object's fields (I have checked them too).

I guess it is worth noticing that the sandbox is running on Summer 17 (API 40) already, while production is in Spring 17 (API 39). However, the component is using API 36.

Best Answer

Answer for part two: I thought this was fixed but maybe not - try wrapping whatever is inside your aura:if in a span tag.

This is because the aura:if can become confused if you have an aura:iteration direction inside it (They use a system of inline comments to store data and can step on each other's toes) - which I'm not sure if you do, but it sounds likely.

eg:

<aura:if >
  <span>
    <aura:iteration items="{!v. invoiceitems}" var="item">
      <other stuff>        
    </aura:iteration>
  </span>
</aura:if>

Oh, and this makes sense - this has been fixed in the sandbox, but you still need the span in production.

Related Topic