You need to sign in to do that
Don't have an account?
Greg Finzer
How to handle validation errors in a lightning add/edit modal popup?
I have created an Add/Edit modal popup that is working well. I have a couple required validations and also a couple custom validation rules. How do I get the validation errors and display them?
Here is my component:
Here is my controller:
Here is my helper:
Here is my component:
<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId" access="global" controller="FRCAddRenoPopupController"> <aura:attribute name="accountId" type="Id"/> <aura:attribute name="PageHeading" type="String" default="Add Renovation" /> <aura:attribute name="reno" type="FRC_Renovation__c" default="{'sobjectType' : 'FRC_Renovation__c', 'Id' : '', 'Name' : '', 'Property__c' : '', 'Renovation_Start_Date__c' : '', 'Renovation_End_Date__c' : '', 'Renovation_Notes__c' : '', 'Scope_Confirmed__c' : false }"/> <lightning:button label="Add Renovation" iconName="utility:new_window" iconPosition="left" variant="brand" onclick="{!c.newPopup}" /> <aura:method name="editPopupMethod" action="{!c.editPopup}" access="public"> <aura:attribute name="columnIdentifier" type="String" /> </aura:method> <div role="dialog" tabindex="-1" aria-labelledby="header43" aura:id="renoAddModal" class="slds-modal slds-modal_large"> <div class="slds-modal__container" style="width: 65%;"> <div class="slds-modal__header" style="font-size: 1.5em"> {!v.PageHeading} </div> <div class="slds-modal__content slds-p-around--medium"> <div class="slds-p-left_xx-large slds-p-right_xx-large" style="padding-left:0px"> <div class="slds-page-header" style="padding-top: 9px; padding-bottom: 9px;padding-right: 9px;"> <h3 style="font-size: 1rem;" title="">Renovation Information</h3> </div> </div> <div class="slds-grid slds-p-top_medium"> <div class="slds-size_11-of-12 slds-p-left_xx-large slds-p-horizontal_x-large " > <lightning:input label="Renovation Name" required="true" name="renovationName" value="{!v.reno.Name}"/> </div> </div> <div class="slds-grid slds-p-top_x-small"> <div class="slds-size_6-of-12 slds-p-left_xx-large slds-p-horizontal_x-large " > <ui:inputDate label="Renovation Start Date" aura:id="renovationStartDate" required="true" value="{!v.reno.Renovation_Start_Date__c}" displayDatePicker="true" format="MM/dd/yyyy"/> </div> <div class="slds-size_5-of-12 slds-p-left_xx-small slds-p-horizontal_x-large " > <ui:inputDate label="Renovation End Date" aura:id="renovationEndDate" value="{!v.reno.Renovation_End_Date__c}" displayDatePicker="true" format="MM/dd/yyyy"/> </div> </div> <div aura:id="scopeConfirmedDiv" class="slds-grid slds-p-top_medium"> <div class="slds-size_11-of-12 slds-p-left_xx-large slds-p-horizontal_x-large " > <lightning:input label="Scope Confirmed" type="checkbox" name="scopeConfirmed" checked="{!v.reno.Scope_Confirmed__c}"/> </div> </div> <div class="slds-grid slds-p-top_medium"> <div class="slds-size_11-of-12 slds-p-left_xx-large slds-p-horizontal_x-large " > Renovation Notes<br /> <lightning:inputRichText label="Renovation Notes" value="{!v.reno.Renovation_Notes__c}" /> </div> </div> </div> <div class="slds-modal__footer"> <lightning:button label="Save" onclick="{!c.saveModal}" /> <lightning:button label="Cancel" onclick="{!c.closeNewModal}" /> </div> </div> </div> <div aura:id="Modalbackdrop" class="slds-backdrop"></div> </aura:component>
Here is my controller:
({ editPopup : function(component, event, helper) { var args = event.getParam("arguments"); var columnIdentifier = args.columnIdentifier; var action = component.get("c.loadReno"); action.setParams({renoID : columnIdentifier}); action.setCallback(this, function(response) { var state = response.getState(); if (state === "SUCCESS") { component.set("v.PageHeading", "Edit Renovation"); var record = response.getReturnValue(); component.set("v.reno.Id", record.Id); component.set("v.reno.Name", record.Name); component.set("v.reno.Property__c", record.Property__c); component.set("v.reno.Renovation_Start_Date__c", record.Renovation_Start_Date__c); component.set("v.reno.Renovation_End_Date__c", record.Renovation_End_Date__c); component.set("v.reno.Renovation_Notes__c", record.Renovation_Notes__c); component.set("v.reno.Scope_Confirmed__c", record.Scope_Confirmed__c); helper.applyShowFormStyles(component); } else if (state === "ERROR") { var errors = response.getError(); if (errors) { if (errors[0] && errors[0].message) { console.log("Error message: " + errors[0].message); } } else { console.log(response.getReturnValue()); } } }); $A.enqueueAction(action); }, newPopup : function(component, event, helper) { //Initialize Fields component.set("v.PageHeading", "Add Renovation"); component.set("v.reno.Id", ""); component.set("v.reno.Name", ""); component.set("v.reno.Property__c", ""); component.set("v.reno.Renovation_Start_Date__c", ""); component.set("v.reno.Renovation_End_Date__c", ""); component.set("v.reno.Renovation_Notes__c", ""); component.set("v.reno.Scope_Confirmed__c", false); helper.applyShowFormStyles(component); //Hide the scope confirmed checkbox when adding a renovation var cmpScopeConfirmed = component.find('scopeConfirmedDiv'); $A.util.addClass(cmpScopeConfirmed, 'slds-hide'); }, closeNewModal : function(component, event, helper) { helper.applyHideFormStyles(component); }, saveModal : function(component, event, helper){ var renoAttr = component.get("v.reno"); var accountIdAttr = component.get("v.accountId"); console.log(renoAttr.Id); if (renoAttr.Id == '') { helper.insertReno(component, helper, renoAttr, accountIdAttr); } else { helper.updateReno(component, helper, renoAttr); } }, })
Here is my helper:
({ applyHideFormStyles : function(component) { var cmpTarget = component.find('renoAddModal'); $A.util.removeClass(cmpTarget, 'slds-fade-in-open'); var cmpBack = component.find('Modalbackdrop'); $A.util.removeClass(cmpBack,'slds-backdrop_open'); var cmpScopeConfirmed = component.find('scopeConfirmedDiv'); $A.util.removeClass(cmpScopeConfirmed, 'slds-hide'); }, applyShowFormStyles : function(component) { var cmpTarget = component.find('renoAddModal'); $A.util.addClass(cmpTarget, 'slds-fade-in-open'); var cmpBack = component.find('Modalbackdrop'); $A.util.addClass(cmpBack, 'slds-backdrop_open'); }, insertReno : function(component, helper, renoAttr, accountIdAttr) { var action = component.get("c.insertReno"); action.setParams({reno : renoAttr, accountId : accountIdAttr}); action.setCallback(this, function(response) { var state = response.getState(); if (state === "SUCCESS") { $A.get('e.force:refreshView').fire(); helper.applyHideFormStyles(component); } else if (state === "ERROR") { var errors = response.getError(); if (errors) { if (errors[0] && errors[0].message) { console.log("Error message: " + errors[0].message); } } else { console.log(response.getReturnValue()); } } }); $A.enqueueAction(action); }, updateReno : function(component, helper, renoAttr) { var action = component.get("c.updateReno"); action.setParams({reno : renoAttr}); action.setCallback(this, function(response) { var state = response.getState(); if (state === "SUCCESS") { $A.get('e.force:refreshView').fire(); helper.applyHideFormStyles(component); } else if (state === "ERROR") { var errors = response.getError(); if (errors) { if (errors[0] && errors[0].message) { console.log("Error message: " + errors[0].message); } } else { console.log(response.getReturnValue()); } } }); $A.enqueueAction(action); } })
If you want to get the Validation Error in Lightning while your inserting or Updating the FRC_Renovation__c record then you have to fire the Aura Exception from your Apex Class Like below :
Public static lead insertReno(FRC_Renovation__c reno ,Id accountId)
{
String errormsg =''
try{
insert reno;
}
catch(DmlException ex){
for(Integer i=0; i < ex.getNumDml(); i++){
errormsg =+ ex.getDmlMessage(i) + '\n';
}
throw new AuraHandledException(errormsg);
}
catch(Exception e){
throw new AuraHandledException(e.getMessage());
}
finally{
}
}
In JS Controller : (This will show the errors in Toast Msg)
insertReno : function(component, helper, renoAttr, accountIdAttr) {
var action = component.get("c.insertReno");
action.setParams({reno : renoAttr, accountId : accountIdAttr});
action.setCallback(this, function(response) {
var state = response.getState();
if (state === "SUCCESS") {
$A.get('e.force:refreshView').fire();
helper.applyHideFormStyles(component);
}
else if (state === "ERROR") {
var errors = response.getError();
if (errors) {
if (errors[0] && errors[0].message) {
var toastEvent = $A.get("e.force:showToast");
toastEvent.setParams({
"title": "Error!",
"message": errors[0].message,
'type': 'error'
});
toastEvent.fire();
console.log("Error message: " +
errors[0].message);
}
} else {
console.log("Unknown error");
}
}
});
$A.enqueueAction(action);
}
if you want to show the Error messages inside the Component instead of Toast then Add one More Attribute to store the Error Message and create the new div element or area in top of the component to display the error message and then use the Aura:if to control this error div only display if the arror attribute is not empty.
Can you please Let me know if it helps or not!!!
If it helps don't forget to mark this as a best answer!!!
Thanks,
Maharajan.C
All Answers
Did you try?
<lightning:messages />
Very little documentation exists on it (obsolete now?)
https://github.com/SalesforceFoundation/Cumulus/blob/master/src/aura/BGE_EntryForm/BGE_EntryForm.cmp
https://www.oreilly.com/library/view/learning-salesforce-lightning/9781787124677/39dd0d17-527e-490f-bfa8-15a04b71db4f.xhtml
If you want to get the Validation Error in Lightning while your inserting or Updating the FRC_Renovation__c record then you have to fire the Aura Exception from your Apex Class Like below :
Public static lead insertReno(FRC_Renovation__c reno ,Id accountId)
{
String errormsg =''
try{
insert reno;
}
catch(DmlException ex){
for(Integer i=0; i < ex.getNumDml(); i++){
errormsg =+ ex.getDmlMessage(i) + '\n';
}
throw new AuraHandledException(errormsg);
}
catch(Exception e){
throw new AuraHandledException(e.getMessage());
}
finally{
}
}
In JS Controller : (This will show the errors in Toast Msg)
insertReno : function(component, helper, renoAttr, accountIdAttr) {
var action = component.get("c.insertReno");
action.setParams({reno : renoAttr, accountId : accountIdAttr});
action.setCallback(this, function(response) {
var state = response.getState();
if (state === "SUCCESS") {
$A.get('e.force:refreshView').fire();
helper.applyHideFormStyles(component);
}
else if (state === "ERROR") {
var errors = response.getError();
if (errors) {
if (errors[0] && errors[0].message) {
var toastEvent = $A.get("e.force:showToast");
toastEvent.setParams({
"title": "Error!",
"message": errors[0].message,
'type': 'error'
});
toastEvent.fire();
console.log("Error message: " +
errors[0].message);
}
} else {
console.log("Unknown error");
}
}
});
$A.enqueueAction(action);
}
if you want to show the Error messages inside the Component instead of Toast then Add one More Attribute to store the Error Message and create the new div element or area in top of the component to display the error message and then use the Aura:if to control this error div only display if the arror attribute is not empty.
Can you please Let me know if it helps or not!!!
If it helps don't forget to mark this as a best answer!!!
Thanks,
Maharajan.C
Thanks for your help. I ended up doing something similar:
Controller:
FRCHelper class:
My Helper Class in the Lightning Component:
I just put in an error messages div referring to an attribute instead of the toast: