0

I wanted a Quick Action button that also allowed for uploading a file. I have some fields that are picklist, and some fields that are dependent picklists. It worked fine until added the code I found for the dependent picklist fields and tried to add value="..." to

<ui:inputSelect aura:id="ERIDT1__Interview_Stage__c" value="{!v.Interview.ERIDT1__Interview_Stage__c}" change="{!c.onControllerFieldChange}"/>

and

<ui:inputSelect aura:id="ERIDT1__Interview_Decision__c" value="{!v.Interview.ERIDT1__Interview_Decision__c}" disabled="{!v.isDependentDisable}"/>

. When I add the value I get this error: Error

If I don't add value there is no error, but it doesn't save the field. Thanks in advance for any help.

Apex Class:

public class Client_Int_Btn_Ctrl{

/*Method to save record of Forms, Documents & Evaluations with its related attachments
    @Param - interview   ==> record of Interview
    @Param - CTId       ==> Client Tracker Id
*/
@AuraEnabled
public static string saveRecord(ERIDT1__Forms_Documents_Evaluations__c interview, Id CTId)
{
    try
    {
        system.debug('Interview ? ' + interview);
        interview.ERIDT1__Client_Tracker__c = CTId;
        interview.recordTypeId = Schema.SObjectType.ERIDT1__Forms_Documents_Evaluations__c.getRecordTypeInfosByName().get('Interview Form').getRecordTypeId();
        upsert interview;
    }

    catch(Exception e)
    {
        throw new AuraHandledException('This is the error: ' + e.getMessage());
    }

    return null;
}
@AuraEnabled  
public static Map<String,List<String>> getDependentOptionsImpl(string objApiName , string contrfieldApiName , string depfieldApiName){
    system.debug(objApiName + '##' + contrfieldApiName + '###' + depfieldApiName);

    String objectName = objApiName.toLowerCase();
    String controllingField = contrfieldApiName.toLowerCase();
    String dependentField = depfieldApiName.toLowerCase();

    Map<String,List<String>> objResults = new Map<String,List<String>>();
        //get the string to sobject global map
    Map<String,Schema.SObjectType> objGlobalMap = Schema.getGlobalDescribe();

    if (!Schema.getGlobalDescribe().containsKey(objectName)){
        System.debug('OBJNAME NOT FOUND --.> ' + objectName);
        return null;
     }

    Schema.SObjectType objType = Schema.getGlobalDescribe().get(objectName);
    if (objType==null){
        return objResults;
    }
    Bitset bitSetObj = new Bitset();
    Map<String, Schema.SObjectField> objFieldMap = objType.getDescribe().fields.getMap();
    //Check if picklist values exist
    if (!objFieldMap.containsKey(controllingField) || !objFieldMap.containsKey(dependentField)){
        System.debug('FIELD NOT FOUND --.> ' + controllingField + ' OR ' + dependentField);
        return objResults;     
    }

    List<Schema.PicklistEntry> contrEntries = objFieldMap.get(controllingField).getDescribe().getPicklistValues();
    List<Schema.PicklistEntry> depEntries = objFieldMap.get(dependentField).getDescribe().getPicklistValues();
     objFieldMap = null;
    List<Integer> controllingIndexes = new List<Integer>();
    for(Integer contrIndex=0; contrIndex<contrEntries.size(); contrIndex++){            
        Schema.PicklistEntry ctrlentry = contrEntries[contrIndex];
        String label = ctrlentry.getLabel();
        objResults.put(label,new List<String>());
        controllingIndexes.add(contrIndex);
    }
    List<Schema.PicklistEntry> objEntries = new List<Schema.PicklistEntry>();
    List<PicklistEntryWrapper> objJsonEntries = new List<PicklistEntryWrapper>();
    for(Integer dependentIndex=0; dependentIndex<depEntries.size(); dependentIndex++){            
           Schema.PicklistEntry depentry = depEntries[dependentIndex];
           objEntries.add(depentry);
    } 
    objJsonEntries = (List<PicklistEntryWrapper>)JSON.deserialize(JSON.serialize(objEntries), List<PicklistEntryWrapper>.class);
    List<Integer> indexes;
    for (PicklistEntryWrapper objJson : objJsonEntries){
        if (objJson.validFor==null || objJson.validFor==''){
            continue;
        }
        indexes = bitSetObj.testBits(objJson.validFor,controllingIndexes);
        for (Integer idx : indexes){                
            String contrLabel = contrEntries[idx].getLabel();
            objResults.get(contrLabel).add(objJson.label);
        }
    }
    objEntries = null;
    objJsonEntries = null;
    system.debug('objResults--->' + objResults);
    return objResults;
}
}

Component:

<aura:component controller="Client_Int_Btn_Ctrl" implements="force:lightningQuickActionWithoutHeader,force:appHostable,lightning:actionOverride,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes" access="global" >
<aura:html tag="style">
    .cuf-content {
    padding: 0 0rem !important;
    }
    .slds-p-around--medium {
    padding: 0rem !important;
    }       
    .slds-modal__content{
    overflow-y:hidden !important;
    height:unset !important;
    max-height:unset !important;
    }
</aura:html>
<aura:attribute name="recordId" type="Id" />
<aura:attribute name="Interview" type="ERIDT1__Forms_Documents_Evaluations__c" default="{ 'sobjectType' : 'ERIDT1__Forms_Documents_Evaluations__c' }"/>
<aura:attribute name="Error" type="String" />
<aura:attribute name="ObjectName" type="String" default="ERIDT1__Forms_Documents_Evaluations__c"/>
<aura:handler name="init" value="{!this}" action="{!c.doInit}" />
<aura:attribute name="depnedentFieldMap" type="map" description="store controller(key)--> dependent(values) picklist value as a map." />
<aura:attribute name="isDependentDisable" type="boolean" default="true" description="use for, make disbale depandent field." />

<form class="slds-form--stacked mainForm">
    <aura:if isTrue="{! v.Error != null}">
            <div class="forcePageError">
                <div class="genericNotification">
                    <span class="genericError uiOutputText">
                        Review the errors on this page.
                    </span>
                </div>
            </div>
            <p style="color:red">{!v.Error}</p>
    </aura:if>
    <br/>
    <div class="inputText">
        <div class="slds">
            <div class="slds slds-grid slds-wrap slds-grid--pull-padded">
                <div class="slds-col--padded slds-col--padded slds-size--1-of-2 slds-large-size--6-of-12">
                    <!--Controller Field-->
                    <div class="slds-form-element">
                        <label class="slds-form-element__label myLabel">Interview Stage</label>
                        <div class="slds-form-element__control">
                            <ui:inputSelect aura:id="ERIDT1__Interview_Stage__c" value="{!v.Interview.ERIDT1__Interview_Stage__c}" change="{!c.onControllerFieldChange}"/>
                        </div>
                    </div>
                </div>
                <div class="slds-col--padded slds-size--1-of-2 slds-large-size--6-of-12">
                    <!--Dependent Field-->
                    <div class="slds-form-element">
                        <label class="slds-form-element__label myLabel">Interview Decision</label>
                        <div class="slds-form-element__control">
                            <ui:inputSelect aura:id="ERIDT1__Interview_Decision__c" disabled="{!v.isDependentDisable}"/>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</form><br/><br/>
<div class="modal-footer slds-modal__footer"  style="height:60px">
    <lightning:button class="slds-button slds-button--neutral" onclick="{!c.closeModel}" >Cancel</lightning:button> 
    <lightning:button class="slds-button slds-button--brand"  onclick="{!c.saveRecordWrapper}">Save</lightning:button>
</div>
</aura:component>

Controller:

({
doInit:function(component,event,helper){
    helper.fetchPicklistValues(component, 'eridt1__interview_stage__c', 'eridt1__interview_decision__c');
},

saveRecordWrapper:function(component,event,helper)
{
    var btn = event.getSource();
    btn.set("v.disabled", true);

    var Interview= component.get("v.Interview");
    helper.upload(component,Interview,btn);
},

closeModel: function(component, event, helper) {
    component.set("v.Error", null);
    component.set("v.Interview", null);
    $A.get("e.force:closeQuickAction").fire();


 },

   onControllerFieldChange: function(component, event, helper) {

      var controllerValueKey = event.getSource().get("v.value");

  var Map = component.get("v.depnedentFieldMap");

  if (controllerValueKey != '--- None ---') {

     var ListOfDependentFields = Map[controllerValueKey];
     helper.fetchDepValues(component, ListOfDependentFields);

  } else {
     var defaultVal = [{
        class: "optionClass",
        label: '--- None ---',
        value: '--- None ---'
     }];
     component.find('conState').set("v.options", defaultVal);
     component.set("v.isDependentDisable", true); 
  }
   }
})

And Helper:

({

upload: function(component, Interview, btn) {

    var action = component.get("c.saveRecord");
    action.setParams({
        interview: Interview,
        CTId:component.get("v.recordId")
    });
    action.setCallback(this, function(response) {
        var state = response.getState();

        if(state === "SUCCESS")
        {
            component.set("v.Error", null);
            component.set("v.Interview", null);
            btn.set("v.disabled", false);
            $A.get("e.force:closeQuickAction").fire();  
            $A.get('e.force:refreshView').fire();

            var toastEvent = $A.get("e.force:showToast");
            toastEvent.setParams({
                type: 'success',
                message: 'New Interview created. To edit entire record, look in the related lists.'
            });
            toastEvent.fire();
        }
        if(state === "ERROR")
        {
            var errors = response.getError();
            if (errors) {
                if(errors[0] && errors[0].message )
                {
                    component.set("v.Error", errors[0].message);
                }
            }
            btn.set("v.disabled", false);
        }

    });
    $A.enqueueAction(action);
},
fetchPicklistValues: function(component, controllerField, dependentField) {
  var action = component.get("c.getDependentOptionsImpl");

  action.setParams({
     'objApiName': component.get("v.ObjectName"),
     'contrfieldApiName': controllerField,
     'depfieldApiName': dependentField
  });
  action.setCallback(this, function(response) {
     if (response.getState() == "SUCCESS") {
        var StoreResponse = response.getReturnValue();

        component.set("v.depnedentFieldMap", StoreResponse);


        var listOfkeys = []; // for store all map keys (controller picklist values)
        var ControllerField = []; // for store controller picklist value to set on ui field. 

        for (var singlekey in StoreResponse) {
           listOfkeys.push(singlekey);
        }

        if (listOfkeys != undefined && listOfkeys.length > 0) {
           ControllerField.push({
              class: "optionClass",
              label: "--- None ---",
              value: "--- None ---"
           });
        }

        for (var i = 0; i < listOfkeys.length; i++) {
           ControllerField.push({
              class: "optionClass",
              label: listOfkeys[i],
              value: listOfkeys[i]
           });
        }
        component.find('ERIDT1__Interview_Stage__c').set("v.options", ControllerField);
     }
  });
  $A.enqueueAction(action);


},

   fetchDepValues: function(component, ListOfDependentFields) {
      var dependentFields = [];

  if (ListOfDependentFields != undefined && ListOfDependentFields.length > 0) {
     dependentFields.push({
        class: "optionClass",
        label: "--- None ---",
        value: "--- None ---"
     });

  }
  for (var i = 0; i < ListOfDependentFields.length; i++) {
     dependentFields.push({
        class: "optionClass",
        label: ListOfDependentFields[i],
        value: ListOfDependentFields[i]
     });
  }
  component.find('ERIDT1__Interview_Decision__c').set("v.options", dependentFields);
  component.set("v.isDependentDisable", false);
   }

})
5
  • 1
    That’s alot of code, aren’t you able to create a minimal reproduceable code sample? It will be easier to help you out. Thanks
    – glls
    Jul 13 '18 at 22:47
  • 1
    Additionally, is there anything stopping you from using a lightning record edit form?
    – glls
    Jul 13 '18 at 22:48
  • Lack of knowledge is the only thing stopping me! I will research the lightning record edit form and see if I can minimize the code.
    – Jennifer
    Jul 14 '18 at 1:10
  • it will also save you alot of server requests and will manage FLS and cRUD operations so it is worth looking into. Cheers
    – glls
    Jul 14 '18 at 2:06
  • Thanks again glls! I read and worked a ton yesterday and I got it all working and with SO much less code using lighting:recordEditForm.
    – Jennifer
    Jul 15 '18 at 14:55
1

Just adding this for future users trying to implement custom components for interacting with records or creating new ones.

When possible, try leveraging the

Represents a record edit layout that displays one or more fields, provided by lightning:outputField. This component requires API version 41.0 and later. A lightning:recordEditForm component is a wrapper component that accepts a record ID and is used to display one or more fields and labels associated with that record using lightning:inputField. lightning:recordEditForm requires a record ID to display the fields on the record. It doesn't require additional Apex controllers or Lightning Data Service to display record data. This component also takes care of field-level security and sharing for you, so users see only the data they have access to.

Basic Usage Sample:

<aura:component>
<lightning:recordEditForm recordId="003XXXXXXXXXXXXXXX" objectApiName="Contact">
    <lightning:messages />
    <lightning:inputField fieldName="FirstName" />
    <lightning:inputField fieldName="LastName" />
    <lightning:inputField fieldName="Email" />
    <lightning:button class="slds-m-top_small" variant="brand" type="submit" name="update" label="Update" />
</lightning:recordEditForm>
</aura:component>

downside(s) I have experienced:

  • May take up to a second or two to load

Upsides:

  • Easy setup (minimal code)
  • Less code to maintain
  • Handles Errors and displays to users
  • Handles CRUD (No Apex)
  • Handles FLS
  • Supports Dependant Picklists

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.