Record Type Selector Quick Action in Lightning

What if you want to create a child record from the parent record page in lightning? What is most feasible and quick solution here?

Of course Lightning Object Specific Quick Action, right?

Well, there is a small issue, what if you want to select the “Record Type” before creating the record? Yes,  object-specific out of the box quick action does not support dynamic record type selection, however, you can select the default record type when creating the quick action.

So what is the solution here? 🤔

The solution is to create a Lightning Component which allows you to select the record type before creating the record. So let’s create our component which:

  • Can be added as Quick Action
  • Should allow us to select available “Record Types”
  • Should allow us to create the child record

Scenario: We need a quick action on Account record detail page, which can create child Contact records using selected record type.

 

Your code should look like this 

RecordTypeSelector.apxc

public class RecordTypeSelector{

    /*

     * This function will fetch the RecordTypes of

     * provided object and will return a map of

     * recordTypeId and recordTypeNames

     * it excludes 'master' record type

     * */

    public static Map<Id, String> recordtypemap;

@AuraEnabled        

    public static Map<Id, String> fetchRecordTypeValues(String objectName){

        List<Schema.RecordTypeInfo> recordtypes = Schema.getGlobalDescribe().get(objectName).getDescribe().getRecordTypeInfos();    

        recordtypemap = new Map<Id, String>();

        for(RecordTypeInfo rt : recordtypes){

            if(rt.getName() != 'Master' && rt.getName().trim() != '')

            recordtypemap.put(rt.getRecordTypeId(), rt.getName());

        }        

        return recordtypemap;

    }

}

 

CreateContactWithRecordType.cmp

<aura:component controller="RecordTypeSelector" implements="force:lightningQuickActionWithoutHeader,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId" access="global" >

    

    <aura:attribute name="lstOfRecordType" type="String[]" />

    <aura:attribute name="mapOfRecordType" type="Map" />

    

    <!-- Fetch all available record types after component construction but before rendering -->

    <aura:handler name="init" value="{!this}" action="{!c.fetchListOfRecordTypes}"/>

    

    <lightning:layout multipleRows="true" horizontalAlign="center">

        <lightning:layoutItem flexibility="auto" padding="around-small"

                              size="12"

                              largeDeviceSize="12"

                              mediumDeviceSize="12"

                              smallDeviceSize="12">

            <lightning:formattedText value="Select Contact Record Type" />

        </lightning:layoutItem>

        <lightning:layoutItem flexibility="auto" padding="around-small"

                              size="12"

                              largeDeviceSize="12"

                              mediumDeviceSize="12"

                              smallDeviceSize="12">

            

            <!-- select to hold all available record type names list -->

            <lightning:select aura:id="recordTypePickList" name="selectRecordType" label="Select a Record Type">

                <option value="" text="Select Record Type"/>

                <aura:iteration items="{!v.lstOfRecordType}" var="item">

                    <option value="{!item}" text="{!item}"/>

                </aura:iteration>

            </lightning:select>

            

        </lightning:layoutItem>

        <lightning:layoutItem flexibility="auto" padding="around-small"

                              size="3"

                              largeDeviceSize="3"

                              mediumDeviceSize="3"

                              smallDeviceSize="6">

            <lightning:button variant="brand" label="Next" onclick="{!c.createRecord}"/>

        </lightning:layoutItem>

        <lightning:layoutItem flexibility="auto" padding="around-small"

                              size="3"

                              largeDeviceSize="3"

                              mediumDeviceSize="3"

                              smallDeviceSize="6">

            <lightning:button variant="neutral" label="Cancel" onclick="{!c.closeModal}" />

        </lightning:layoutItem>

    </lightning:layout>

</aura:component>

 

CreateContactWithRecordTypeController.js

({

    /*

     * This method is being called from init event

     * to fetch all available recordTypes

     * */

    fetchListOfRecordTypes: function(component, event, helper) {

        var action = component.get("c.fetchRecordTypeValues");

        

        //pass the object name here for which you want

        //to fetch record types

        action.setParams({

            "objectName" : "Contact"

        });

        

        action.setCallback(this, function(response) {

            var mapOfRecordTypes = response.getReturnValue();

            component.set("v.mapOfRecordType", mapOfRecordTypes);

            

            var recordTypeList = [];

            //Creating recordTypeList from retrieved Map

            for(var key in mapOfRecordTypes){

                recordTypeList.push(mapOfRecordTypes[key]);

            }

            

            if(recordTypeList.length == 0){//Object does not have any record types

                //Close Quick Action Modal here

                helper.closeModal();

                

                //Calling CreateRecord modal here without providing recordTypeId

                helper.showCreateRecordModal(component, "", "Contact");

            } else{

            component.set("v.lstOfRecordType", recordTypeList);

            }

            

        });

        $A.enqueueAction(action);

    },

    

    /*

     * This method will be called when "Next" button is clicked

     * It finds the recordTypeId from selected recordTypeName

     * and passes same value to helper to create a record

     * */

    createRecord: function(component, event, helper, sObjectRecord) {

        var selectedRecordTypeName = component.find("recordTypePickList").get("v.value");

        if(selectedRecordTypeName != ""){

            var selectedRecordTypeMap = component.get("v.mapOfRecordType");

            var selectedRecordTypeId;

            

            //finding selected recordTypeId from recordTypeName

            for(var key in selectedRecordTypeMap){

                if(selectedRecordTypeName == selectedRecordTypeMap[key]){

                    selectedRecordTypeId = key;//match found, set value in selectedRecordTypeId variable

                    break;

                }

            }

            //Close Quick Action Modal here

            helper.closeModal();

            

            //Calling CreateRecord modal here without providing recordTypeId

            helper.showCreateRecordModal(component, selectedRecordTypeId, "Contact");

        } else{

            alert('You did not select any record type');

        }

        

    },

    

    /*

     * closing quickAction modal window

     * */

    closeModal : function(component, event, helper){

        helper.closeModal();

    }

})

 

CreateContactWithRecordTypeHelper.js

({

    /*

     * This methid takes recordTypeId and entityTypeName parameters

     * and invoke standard force:createRecord event to create record

     * if recordTypeIs is blank, this will create record under master recordType

     * */

    showCreateRecordModal : function(component, recordTypeId, entityApiName) {

        debugger;

        var createRecordEvent = $A.get("e.force:createRecord");

        if(createRecordEvent){ //checking if the event is supported

            if(recordTypeId){//if recordTypeId is supplied, then set recordTypeId parameter

                createRecordEvent.setParams({

                    "entityApiName": entityApiName,

                    "recordTypeId": recordTypeId,

                    "defaultFieldValues": {

                "AccountId": component.get("v.recordId")

                    }

                    

                });

            } else{//else create record under master recordType

                createRecordEvent.setParams({

                    "entityApiName": entityApiName,

                    "defaultFieldValues": {

                          "AccountId": component.get("v.recordId")

                    }

                });

            }

            createRecordEvent.fire();

        } else{

            alert('This event is not supported');

        }

    },

    

    /*

     * closing quickAction modal window

     * */

    closeModal : function(){

        var closeEvent = $A.get("e.force:closeQuickAction");

        if(closeEvent){

        closeEvent.fire();

        } else{

            alert('force:closeQuickAction event is not supported in this Ligthning Context');

        }

    },

})

 

Create a Lightning Component Quick Action

Once you have developed your lightning component, you need to add this as a quick action on Account Object. Follow this gif to create a new quick action named “Create Contact” using CreateContactWithRecordType component:

 

Add your quick action to Account Page Layout

Now add your quick action “Create Contact”  to Account Object page layout to display this action on the page. Follow this gif:

What we did

  • We have created an Apex Controller RecordTypeSelector to fetch all available record type list.
  • We have implemented force:lightningQuickActionWithoutHeader interface in our component to make it available for use as quick action.
  • We have created lightning:select component to hold record type list.
  • We have used force:createRecord standard event to create a new record.
  • We have passed “recordTypeId” parameter to force:createRecord event to create a record with selected record type name.
  • We have supplied “defaultFieldValues” parameter to pass AccountId to new Contact Record.
  • Created new lightning component quick action named “Create Contact”.
  • Added quick action to Account Page layout.

 

Output

 

The code should be self-explanatory as I have added comments everywhere. Please post a comment if you have any queries.

 

That’s it guys!! Your new lightning component is ready and available for use. 🤗

Manish Choudhari

I am a certified Salesforce Application & System Architect and Developer working on Salesforce Technology since 2014. Currently, I have 14 Salesforce certifications along with OCPJP (Oracle Certified Profession JavaSE6 Programmer) working in Salesforce.com Hyderabad as a Technical Engineer. Writing technical blogs, learning new technologies and frameworks and sharing knowledge is my hobby.

This Post Has 21 Comments

  1. Avatar

    Hi Manish, it helped a lot. I have a trouble in one scenario, I hope you can help me. please send an email to ak144.sfdc@gmail.com, so that I can be in contact with you.

  2. Avatar

    How to hide default popup of Quick Action.One Default Dialogue box is populated automatically when we are clicking on Quick Action.

    1. Avatar

      Hey Keyur,

      Which interface you are using:
      1. force:lightningQuickActionWithoutHeader
      2. force:lightningQuickAction

      The first one allows a component to display in a panel without additional controls. The component should provide a complete user interface for the action.
      The 2nd additional controls as well.

      You can only use one of these at a time.

      In your case, you should use force:lightningQuickActionWithoutHeader.

  3. Avatar

    Hey Manish ,
    I have a small question here . I don’t want to open the whole edit page while creating the record but rather a small layouts with only fields require to create a new record . So lets say I create a GLobal quick action with a layout and I need to call the layout of the global action from Lightning Component . Opening the whole page on mobile , its not very justified

    1. Avatar

      There are 2 ways to do that:
      1. Either use your own custom component to create a record and limit the number of fields there.
      2. Or if you are using standard event (like in this example), you need to limit the field on page layout associated with the record type. The only problem with this solution is, it will limit the number of field even on the web browser (not only mobile browser)

  4. Avatar

    Hi Manish,

    I have a small issue here, you are pre populate the account name but, I want to populate other fields also can you please suggest me how to do that.

    1. Avatar

      Yes Sandeep,

      You can prepopulate any field of same object which you are creating. In my case, I was creating “Contact” record, so I can populate any contact field.

  5. Avatar

    Hi Manish,
    I have a small issue after creating an event from the opportunity, the Event is not shown on activity related to the Opportunity.
    Would you please help me in this issue.

    1. Avatar

      Hi Behzad,
      Events are treated in a different way in Salesforce. Can you check in newly created event if WhatId matches to opportunity id.

  6. Avatar

    Hi Manish,
    yes, WhatId is matching to the Opportunity Id.
    Thank you very much for your help.

  7. Avatar

    Hi Manish,
    As I am completely new with coding I need again your help,
    I am going to write an Apex Class but I am getting an error I would appreciate if you take a look in the below.

    @isTest
    public class recordtypeSelectorTest {

    static testmethod void testFetchRecordTypes() {
    List values = recordtypeselector.fetchRecordTypeValues();
    }

    static testmethod void testgetRecordTypeId() {
    String recordTypeLabel = ‘Consultant Termin’;
    ID testId = recordtypeSelector.getRecTypeId(recordTypeLabel);
    System.assert(testId != null);
    }

    }

    Error: Compile Error: Method does not exist or incorrect signature: void fetchRecordTypeValues() from the type RecordTypeSelector at line 5 column 46

    1. Avatar

      You need to pass object name to function “fetchRecordTypeValues”. Change your line 5 to something like below:

      recordtypeselector.fetchRecordTypeValues(‘Account’);
      -Replace ‘Account’ with your object name.

  8. Avatar

    Hi,
    Can we disable or hide the ‘Save and New’ button shown on the create record popup?’

  9. Avatar

    Works fine – thank you for the code and the detailed instructions. However: The RecordType selector ignores the profile settings for available record types. Only when saving the new record, the user gets an error message telling him that the record type id isn’t valid for the user.

    How could I fix that?

    1. Avatar

      Hi Ralf,
      You Apex Code runs in system context hence it is giving all the record type even when the user does not have access to that record type. However, you can avoid this by using sample code below:

      List recordTypes = new List();
      for(RecordTypeInfo info: Account.SObjectType.getDescribe().getRecordTypeInfos()) {
      if(info.isAvailable()) {
      recordTypes.add(new SelectOption(info.getRecordTypeId(), info.getName()));
      }
      }

      // Include these next 3 lines to output the results during development and debugging
      for( SelectOption selopt: recordTypes ) {
      System.debug( selopt.getLabel() + ',' + selopt.getValue() );
      }

  10. Avatar

    HI Manish,
    How can auto redirect recordtype based on parentb field.lets say i have parent object Lead having picklist field with value A ,B,C.
    Lead_Age__c is a custom object which is lookup with Lead,and having 2 record type (New Value,Old Value)..
    When I am creating child from parent there is option for record type select.But need to redirect directly recordtype page based on parent picklist value.No need to select any record type.If picklsit value A then at the time of child creation (when click on new button in child it auto direct New value Record type directly and like this.)

    1. Avatar

      This can be done Mahes. While calling e.force.ceateRecord, just pass the recordTypeId you are getting from lead object and skip recordType selection page.

  11. Avatar

    When we use event “e.force:createRecord” for the selected Object(Contact) can we select few fields rather default pagelayout?

    1. Avatar

      You may have to override the “New Contact” page for contact object.

Leave a Reply

Close Menu