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:
However the value isn't displayed on the page's input as it would be expected.
Sandbox:
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.
aura:if
as well?aura:if
tags (that are the parts of the page that should be rendered depending on the value onv.page
). So the tag you are talking about isaura:component
in this case. :) Nothing else around the ifs.$A.util.isEmpty(volume.cm_length)
instead of undefined. Also, you can set breakpoints and step through your code in production to see when, where, what, and whats not getting executed in production.