How to use Fieldsets with Lightning?

How to use Fieldsets with Lightning?

On September 22, 2025, Posted by , In Salesforce Admin, By ,, , With Comments Off on How to use Fieldsets with Lightning?
Fieldsets with Lightning

Fieldsets in Salesforce are powerful because they allow admins to decide which fields appear on a form without developers hardcoding them. When using Lightning Components (Aura), we can render dynamic fields based on a fieldset. The challenge is that Aura-enabled Apex methods cannot return a FieldSet directly.

There are two main approaches:

  1. JSON-based approach (manually build a JSON string and parse it in Lightning).
  2. Wrapper-based approach (use an Apex wrapper class that Lightning can automatically serialize).

Let’s go through both methods step by step. fields.

Here’s a complete example with explanations.

JSON-Based Approach

Step 1: Lightning Component

<aura:component controller="ns.myController">
  <aura:handler name="init" value="{!this}" action="{!c.getForm}" />
  <div class="fields">        
      <form aura:id="myForm"></form>
  </div>    
</aura:component>

This component uses an Apex controller named ns.myController. On initialization (init handler), it triggers the getForm method in the client-side controller. The form body has an aura:id called myForm where fields will be dynamically injected after being generated from the fieldset. The <div> wrapper is just for styling and grouping purposes.

Step 2: Client-Side Controller

getForm : function(component) {
    var action = component.get("c.getFieldSet");  
    var inputOutput = 'input';
    action.setCallback(this, function(a) {
        var jsonFieldset = JSON.parse(a.getReturnValue());
        for(var x=0,xlang=jsonFieldset.length;x<xlang;x++){
            var fieldDef = jsonFieldset[x]; 
            this.createField(component, fieldDef.label, inputOutput+fieldDef.type, fieldDef.name, fieldDef.required);
        }
    });
    $A.enqueueAction(action);
},
createField : function(component, fieldName, fieldType, fieldId, fieldRequired) {
    $A.componentService.newComponentAsync(this,
       function(newField){                                                                        
            var myForm = component.find('myForm');
            var body = myForm.get("v.body");  
            body.push(newField);                                
            myForm.set("v.body",body);
        },
        {
            "componentDef": "markup://ui:"+fieldType,
            "localId": "fieldId",
            "attributes": {
                "values": { label: fieldName,
                           displayDatePicker:true,
                           required:fieldRequired
                          }
            }
        }
    );
}

The getForm method calls the server-side Apex method getFieldSet which returns the fieldset as a JSON string. It then parses the JSON and iterates through each field definition, calling the helper function createField. The createField method dynamically generates new Lightning components using $A.componentService.newComponentAsync. It pushes each new field into the form’s body (v.body). The componentDef dynamically chooses the right input type such as ui:inputText, ui:inputCheckbox, etc., based on the field metadata.

Step 3: Apex Controller

public with sharing class myController {
    static Map<String,String> auraTypes {get; set;}
    public static Map<String,String> getAuraTypes() {
        if(auraTypes!=null) {
            return auraTypes;
        }
        else {
            auraTypes = new Map<String,String>();
            auraTypes.put('BOOLEAN','Checkbox');
            auraTypes.put('DATE','Date');
            auraTypes.put('DATETIME','DateTime');
            auraTypes.put('EMAIL','Email');
            auraTypes.put('NUMBER','Number');
            auraTypes.put('PHONE','Phone');
            auraTypes.put('STRING','Text');            
        }
        return auraTypes;
    }
    @AuraEnabled    
    public static String getFieldSet() {
        String result = '';
        List<Schema.FieldSetMember> fieldset =  SObjectType.Kandidaat__c.FieldSets.formulier.getFields();
        for(Schema.FieldSetMember f : fieldset) {
            if(result!=''){
                result += ',';
            }
            String jsonPart = '{';
            jsonPart += '"label":"'+f.getLabel()+'",';
            jsonPart += '"required":"'+(f.getDBRequired() || f.getRequired())+'",';
            jsonPart += '"type":"'+getAuraTypes().get((f.getType()+'')) +'",';
            jsonPart += '"name":"'+f.getFieldPath()+'"';
            jsonPart += '}';
            result +=jsonPart;
        }
        return '['+result+']';
    }
}

In Apex, the getAuraTypes method maps Salesforce field data types to Aura UI component types like Text, Checkbox, Date, etc. The getFieldSet method retrieves the fieldset from the object Kandidaat__c using Schema.FieldSetMember. For each field in the fieldset, it constructs a JSON object with label, required, type, and name. Finally, it returns the JSON array of all fields. The Lightning component consumes this JSON to dynamically generate the input form.

Explanation: This method works well but requires manual JSON string concatenation, which can be error-prone and less readable.

Wrapper-Based Approach (Cleaner)

Instead of creating JSON manually, you can create a wrapper Apex class with properties like label, type, name, and required. Then, return a list of this wrapper class annotated with @AuraEnabled. This way, you avoid manually concatenating strings for JSON, making the solution cleaner and more maintainable. Example:

Step 1: Wrapper Class

public class FieldWrapper {
    @AuraEnabled public String label {get; set;}
    @AuraEnabled public String type {get; set;}
    @AuraEnabled public String name {get; set;}
    @AuraEnabled public Boolean required {get; set;}
}

This class defines the properties we need for each field: label, type, API name, and required status.

Returning a list of FieldWrapper from Apex means Lightning will automatically deserialize it into JavaScript objects, avoiding manual JSON.parse. This is considered the better practice.

Step 2: Apex Controller Using Wrapper

@AuraEnabled
public static List<FieldWrapper> getFieldSetWrapper() {
    List<FieldWrapper> fieldsList = new List<FieldWrapper>();
    List<Schema.FieldSetMember> fieldset = SObjectType.Kandidaat__c.FieldSets.formulier.getFields();
    for(Schema.FieldSetMember f : fieldset) {
        FieldWrapper fw = new FieldWrapper();
        fw.label = f.getLabel();
        fw.required = (f.getDBRequired() || f.getRequired());
        fw.type = getAuraTypes().get((f.getType()+''));
        fw.name = f.getFieldPath();
        fieldsList.add(fw);
    }
    return fieldsList;
}

This method loops through the fieldset, creates a FieldWrapper for each field, fills in the details, and returns the list. No manual JSON concatenation is required.

Step 3: Lightning Controller

getForm : function(component) {
    var action = component.get("c.getFieldSetWrapper");  
    action.setCallback(this, function(a) {
        var fields = a.getReturnValue();
        for(var i=0; i<fields.length; i++){
            var fieldDef = fields[i]; 
            this.createField(component, fieldDef.label, "input" + fieldDef.type, fieldDef.name, fieldDef.required);
        }
    });
    $A.enqueueAction(action);
}

Since Apex already returns a list of wrapper objects, no JSON.parse is required. The Lightning component directly gets an array of JavaScript objects. This makes the code cleaner and easier to maintain.

Final Answer

The JSON approach works by converting the fieldset into a JSON string and parsing it in Lightning. While effective, it can be messy and prone to errors because of string concatenation.

The Wrapper approach is the recommended way because it uses a strongly-typed Apex class (FieldWrapper) that Lightning automatically serializes into objects. This avoids manual JSON handling, making the solution much cleaner and easier to maintain.

If you are starting fresh, go with the wrapper-based approach. It’s the Salesforce best practice for sending structured data from Apex to Lightning.

JSON vs Wrapper Approach for Fieldsets in Lightning

Feature / AspectJSON-Based ApproachWrapper-Based Approach
Data HandlingApex manually builds a JSON string using string concatenation.Apex returns a list of wrapper objects (FieldWrapper) that Lightning auto-serializes to JSON.
Ease of ImplementationRequires manual string manipulation; error-prone.Cleaner and simpler since Apex handles serialization automatically.
Code ReadabilityHarder to read and maintain, especially with many fields.Easy to read, structured, and maintainable.
DebuggingDebugging JSON string issues can be painful (e.g., missing commas, quotes).Debugging is easier since objects are strongly typed in Apex.
FlexibilityCan be used if you need a very specific JSON format for other integrations.Best suited when data is only consumed within Lightning Components.
PerformanceSlightly slower due to string concatenation and JSON parsing in JS.Faster and more efficient because Apex does the work.
ScalabilityBecomes messy as fieldset grows or more logic is added.Scales well with more fields and complex logic.
Best Use CaseQuick prototype or when JSON is already required for another system.Production-ready Lightning components needing dynamic forms from fieldsets.
Salesforce Best PracticeNot recommended for long-term solutions.Recommended approach for maintainability and clarity.

Conclusion:

Use the Wrapper-based approach in almost all real-world cases because it’s cleaner, more maintainable, and aligns with Salesforce best practices.

The JSON-based approach should only be used when you specifically need a JSON string for integrations or quick prototyping.

Enroll for Career-Building Salesforce Training with Real-Time Projects

Our Salesforce Course is designed to offer a comprehensive understanding of the Salesforce platform, providing you with the essential skills needed to excel in the CRM industry. The program covers key modules like Salesforce Admin, Developer, and AI, blending theoretical concepts with hands-on experience. Through real-world projects and interactive assignments, you will gain the expertise to tackle business challenges using Salesforce solutions. Our expert trainers ensure you acquire both technical proficiency and industry knowledge to thrive in the Salesforce ecosystem.

Beyond technical learning, our Salesforce Training in Boston includes personalized mentorship, certification support, and interview preparation to boost your career prospects. You will have access to extensive study resources, practical project experience, and continuous guidance throughout your training. By the end of the course, you will be fully prepared for certification exams and equipped with real-world problem-solving skills that employers seek. Take the first step in your Salesforce journey with us and unlock limitless career opportunities. Sign up for a Free Demo today!

Comments are closed.