I'm currently building a lightning component for a community builder portal. The whole series of components is reasonably complex but nothing extreme (it's a wizard).
To make things easier I'm using a wrapper class with several objects and sub objects in. Again, it's more than just a simple wrapper class but nothing too complex.
When I bind a field using ui:inputText or ui:inputCheckbox, for example, it appears to be binding (in some cases, not all) to a non-existent field one level up the wrapper class object structure.
Looking at the screenshot below you can see 'Patient_Information_Checked__c'. This field sits on the appointment object. However, as you can see the value is being bound one level up (line 3 on the image) so when I try to save it doesn't submit the correct value...
Here is a shortened version of my component code:
<aura:iteration items="{!v.treatments}" var="treatmentWrapper">
<div>
<aura:if isTrue="{!treatmentWrapper.isSelected == true}">
<ui:inputCheckbox aura:id="checkbox-patientCheckReferrer" value="{!treatmentWrapper.appointment.Patient_Information_Checked__c}" class="checkbox"/>
</aura:if>
</div>
</aura:iteration>
Am I approaching this incorrectly? Or is there a known issue with using the ui:input series of fields and binding? I also tried using the lightning:input and I experience the same issue.
My workaround at the moment is duplicate the field as a String or Boolean in the outer most layer of my wrapper then copy in the value to the correct field on save... This isn't ideal for many obvious reasons.
*** EDIT
At the request for more information, here are full code samples on how to reproduce the issue:
Component:
<aura:component implements="forceCommunity:availableForAllPageTypes" access="global" controller="CommunitiesReferralPatientConfController">
<aura:handler name="init" value="{!this}" action="{!c.init}"/>
<aura:attribute name="recordId" type="String"/>
<aura:attribute name="treatments" type="TreatmentWrapper[]"/>
<aura:iteration items="{!v.treatments}" var="treatmentWrapper">
<div>
<aura:if isTrue="{!treatmentWrapper.isSelected == true}">
<ui:inputCheckbox aura:id="checkbox-patientCheckReferrer" value="{!treatmentWrapper.appointment.Patient_Information_Checked__c}" class="checkbox"/>
</aura:if>
</div>
</aura:iteration>
<ui:button aura:id="nextButton" label="Next" press="{!c.nextStep}" class="slds-button slds-button--brand nextButton"/></aura:component>
Controller.js
({
init : function(component, event, helper) {
var grabReferral = component.get("c.getReferral");
grabReferral.setParams({ referralId : component.get("v.recordId")});
grabReferral.setCallback(this, function(response) {
var treatments = JSON.parse(response.getReturnValue());
component.set("v.treatments", treatments);
});
$A.enqueueAction(grabReferral);
},
nextStep : function(component, event, helper) {
console.log('nextStep');
var treatments = component.get("v.treatments");
console.log(treatments);
}
})
Apex Class
@AuraEnabled
public static TreatmentWrapper getReferral(String referralId)
{
System.debug('#### getDraftReferral');
ContactHelper ch = new ContactHelper();
List<TreatmentWrapper> wrapper = new List<TreatmentWrapper>();
List<Treatment__c> queriedTreatments = [SELECT Id, Name,
(SELECT Id, Active_Appointment__c, FROM__c, Patient_Information_Checked__c FROM Calendar_Entries__r WHERE Active_Appointment__c = true)
FROM Treatment__c WHERE Referral__c = :referralId];
for(Treatment__c treatment : queriedTreatments)
{
TreatmentWrapper tw = new TreatmentWrapper();
tw.isSelected = true;
tw.theTreatment = tw;
for(Calendar_Entry__c entry : treatment.Calendar_Entries__r)
{
tw.appointment = entry;
}
wrapper.add(tw);
}
}
Wrapper Class
public with sharing class TreatmentWrapper
{
@AuraEnabled public Integer treatmentIndex {get; set;}
@AuraEnabled public Boolean isSelected {get; set;}
@AuraEnabled public String treatmentFamily {get; set;}
@AuraEnabled public Treatment__c theTreatment {get; set;}
@AuraEnabled public Calendar_Entry__c appointment {get; set;}
@AuraEnabled public String appointmentNote {get; set;}
}