I have component which holds Object[] attribute. On init action I am loading data in it and showing that for user interaction. All works well and update on input field gets bonded properly with original attribute.
I then call controller function on button click and performs some validations on each element of Object[] and display some error message. After that if I am updating/correcting the values in input field then that value is not getting bind to original Object[] elements.
Maincomponent.cmp:
<aura:attribute name="milestones" type="Object[]" />
<div aura:id="saveconfirmation"></div>
<aura:iteration items="{!v.milestones}" var="mile">
<c:PGP_VariationMilestone milestone="{!mile}" />
</aura:iteration>
<ui:button label="Save" press="{!c.saveVariation}" class="slds-button slds-button--brand" aura:id="savemilestonebutton" />
Here Object[] is list of wrapper class.
PGP_VariationMilestone.cmp
<aura:component controller="PGPVariationCompClass">
<aura:attribute name="milestone" type="Object" />
<div class="slds-form-element" style="width:180px;">
<ui:inputText label="Milestone Number" value="{!v.milestone.name}" disabled="{!(v.milestone.recordId != '') ? 'true' : 'false'}" class="slds-input" labelClass="slds-form-element__label" change="{!c.updateActionOnChange}" />
</div>
<div class="slds-form-element" style="white-space: nowrap;width:130px">
<ui:inputDate aura:id="dueDate" label="Due Date" value="{!v.milestone.dueDate}" displayDatePicker="true" class="slds-input" labelClass="slds-form-element__label" blur="{!c.dateOnChange}" />
</div>
</aura:component>
MainComponentController.js
saveVariation: function(component, event, helper) {
var milestoneArray = component.get('v.milestones') ;
console.log('------in saveVariation milestone-----' + JSON.stringify(component.get('v.milestones')));
var isValid;
var milestonenames = '';
var deliberablenames = '';
var i, j;
// deliverables is a list of wrapper class. each milestoneArray element has list of deliverables[]
for (i = 0; i < milestoneArray.length; i++) {
if (!milestoneArray[i].description ||
!milestoneArray[i].dueDate ||
(!milestoneArray[i].mpifund && milestoneArray[i].miletype == 'Payment')) {
isValid = false;
milestonenames = milestonenames + milestoneArray[i].name + ', ';
}
for (j = 0; j < milestoneArray[i].deliverables.length; j++) {
console.log('------for loop deliverable data----' + JSON.stringify(milestoneArray[i].deliverables[j]));
if (!milestoneArray[i].deliverables[j].dueDate ||
!milestoneArray[i].deliverables[j].startDate ||
!milestoneArray[i].deliverables[j].name ||
!milestoneArray[i].deliverables[j].description) {
isValid = false;
deliberablenames = deliberablenames + milestoneArray[i].deliverables[j].name + ', ';
}
}
}
console.log('----isValid----' + isValid);
if (isValid == true) {
helper.saveVariationHelper(component);
} else {
console.log('------in else of isValid error-----');
$A.createComponents([
["ui:message", {
"title": "Error",
"severity": "error",
"closable": false
}],
["ui:outputText", {
"value": 'Please correct the errors for Miletones:- ' + milestonenames + 'and Deliverables:- ' + deliberablenames,
}]
],
function(components, status) {
if (status === "SUCCESS") {
var message = components[0];
var outputText = components[1];
// set the body of the ui:message to be the ui:outputText
message.set("v.body", outputText);
var saveconfirmation = component.find("saveconfirmation");
// Replace div body with the dynamic component
saveconfirmation.set("v.body", message);
}
}
);
}
}
No error in console. Removing ui:message also didnt worked.
Hope I am clear in explaining the issue. I looked this post also but not sure when fix will be available.
Binding to object values and arrays of objects in Lightning Locker
Best Answer
Something does not look right in your data binding. You declare an
aura:iteration
throughv.milestones
and you declarevar="mile"
. But all your bindings inside the iteration are pointing tov.milestone.propertyName
when they should be pointing tomile
(nov.
because this variable is internal to the iteration).So first off I would try correcting that:
Next, in your JavaScript, you declare
var milestones = component.get('v.milestones');
but then you repeatedly make reference tomilestoneArray
which doesn't exist. I am surprised you are not seeing any console errors!In my sandbox the fix to object binding in Lightning Locker has already rolled out so if you don't have the fix yet, you will soon. I should advise that any fields that do not already exist in the array's objects may face some binding difficulties. Sometimes I also find that if data objects were passed into the component as a parameter, Locker Service will proxy them before your code ever gets to see them and this can screw up the bindings. So in one of my components I basically had to clone the passed-in object, add necessary fields, and then assign it to a new private attribute that is only used internally.
If you made some errors in the code you posted here, please edit your original post and comment to let me know.