1

I'm still relatively new to lightning and APEX, and I've read (it seems like) 100s of posts / examples of how to do this, because it seems like a lot of people ask this, but I cannot make it work. I don't know anything about VisualForce and APEX programming, so those examples are difficult for me to understand and adapt:

use case: get a list of object field names to use in a lightning duallistbox. The object name will be passed in as a parameter.

Here is my latest iteration:

public Map <String, Schema.SObjectType> schemaMap = Schema.getGlobalDescribe();
public String objName {get; set;}
public String selectedField {get; set;}

Public RapidiListConfigController()
{   
    objName = 'InvoiceHeader__c';
}

public List<SelectOption> getObjectNames() 
{
    List<SelectOption> objNames = new List<SelectOption>();
    List<String> entities = new List<String>(schemaMap.keySet());
    entities.sort();
    for(String name : entities)
    {
        objNames.add(new SelectOption(name,name));
    }
    return objNames;
 }

 public Map<String, Schema.SObjectField> getObjectFields(String objName) 
 {
        Map<String, Schema.SObjectType> schemaMap = Schema.getGlobalDescribe();
        Schema.SObjectType ObjectSchema = schemaMap.get(objName);
        Map<String, Schema.SObjectField> fieldMap = ObjectSchema.getDescribe().fields.getMap();
        List<SelectOption> fieldNames = new List<SelectOption>();
        for (String fieldName: fieldMap.keySet()) 
        {  
            fieldNames.add(new SelectOption(fieldName,fieldName));
          //fieldMap.get(fieldName).getDescribe().getLabel();//It provides to get the object fields label.
        }
        return fieldMap;
  } 

But I cannot seem to get the fieldMap or fielNames list back to the component's js controller.

Thanks in advance.

3
  • 1
    Your question says "lightning duallistbox" but you have posted code that looks more related to Visualforce. Can you explain more?
    – Keith C
    Jan 22, 2019 at 15:07
  • 2
    The first problem I notice is that none of your methods are static or @AuraEnabled. That's going to be your first step to make them visible to your Aura component. The second issue you'll encounter will be with List<SelectOption>. The SelectOption object isn't aura enabled so you will get an error if you try to return it from a method. You can either create a new object that acts just like SelectOption or you can return a Map<String, String>. The lightning:dualListBox expects an array of objects with label and value properties so you will need to build with that in mind.
    – nbrown
    Jan 22, 2019 at 15:52
  • @KeithC - that is part of my problem. There's lots of great examples of how to handle this with visualforce and apex, but not finding a lot of options of how to handle this so it works with lightning component.
    – Shawn A
    Jan 22, 2019 at 17:00

2 Answers 2

0

You want to have an Apex Controller to get the field names and return a type that a Lightning Aura Component (LAC) component can understand, e.g. Map. The method in your Apex Controller must be @AuraEnabled. Set up an action in your LAC to get the data from Apex. In the callback of that action, set the proper attribute on your LAC. Put that Lightning Aura Component inside a Visualforce Page using this.

Here's some sample code.

*.cmp

<aura:handler name="init" value="{!this}" action="{!c.init2winit}" />
<aura:attribute name="options" type="List" />
<lightning:dualListbox name="fields"  
                       label= "Fields" 
                       sourceLabel="Available" 
                       selectedLabel="Selected" 
                       fieldLevelHelp="This is a dual listbox" 
                       options="{!v.options}" 
                      />

*.controller.js

init2winit : function(component, event, helper) {
    var action = component.get('c.getObjectFields');
    action.setParams({
        objName: 'Account'
    });

    action.setCallback(this, function(response){
        var options = [];
        var fieldMap = response.getReturnValue(); 
        for (var k in fieldMap) {
            options.push({ value:k, label:fieldMap[k]});
        }
        component.set('v.options', options);
    });
    $A.enqueueAction(action); 
}

*.cls

@AuraEnabled
public static Map<String, String> getObjectFields(String objName) {
    Map<String, String> retVal = new Map<String, String>();
    Map<String, Schema.SObjectField> fieldMap = Schema.getGlobalDescribe().get(objName).getDescribe().fields.getMap();
    for (String fieldName: fieldMap.keySet()) {  
        retVal.put(fieldName, fieldMap.get(fieldName).getDescribe().getLabel());
    }
    return retVal;
}

Ends up looking like this:

screenshot

1

above the Apex methods you have to have @AuraEnabled in order for the JS to communicate with the Apex methods. Example below

APEX

@AuraEnabled
public static Map<String, Schema.SObjectField> getObjectFields(String objName) 
       {
            Map<String, Schema.SObjectType> schemaMap = Schema.getGlobalDescribe();
            Schema.SObjectType ObjectSchema = schemaMap.get(objName);
            Map<String, Schema.SObjectField> fieldMap = ObjectSchema.getDescribe().fields.getMap();
            List<SelectOption> fieldNames = new List<SelectOption>();
            for (String fieldName: fieldMap.keySet()) 
            {  
                fieldNames.add(new SelectOption(fieldName,fieldName));
              //fieldMap.get(fieldName).getDescribe().getLabel();//It provides to get the object fields label.
            }
   Map<String, String> newMap = new Map<String, String>();
   for(String key : fieldNames.keySet()){
      Schema.SObjectType currentSchema = fieldNames.get(key);
      String schemaStr = '' + currentSchema;
      newMap.put(key, schemaStr);
   }
   return newMap;
} 

I'm not sure if you are already doing this but you need to setup the method callout in the JS

JS

myMethod : function(cmp, event, helper){
        var objName = cmp.get('v.objName'); //I'm not sure how you are getting this value from the user this just an example
        var getObjFields = cmp.get('c.getObjectFields');
        getObjFields.setParams({
           'objName' : objName
        });
        getObjFields.setCallback(this, function(response){
        var myMap = response.getReturnValue(); //One thing to note maps in JS are returned as Objects and have to be dealt with accordingly
        // code to add to duallistbox here :  https://developer.salesforce.com/docs/component-library/bundle/lightning:dualListbox/example
        }
        $A.enqueueAction(getObjFields); // Dont forget this or your Apex method won't be invoked
    },

Heres a link to a resource for parsing a JS object which is what your Map will become when it is returned from the Apex

link

5
  • Thanks, Calvin. I have tried various versions of this and I get the error: "AuraEnabled methods do not support return type of Map<String,Schema.SObjectField>"
    – Shawn A
    Jan 22, 2019 at 16:36
  • you will have to convert the Schema.SObjectField into a String before you pass it back. you can do that by creating a new Map<String, String> and looping over the key values in fieldMap, getting their associated Schema, convert into a string, place both the key and new string into the new Map<String, String> Jan 22, 2019 at 17:37
  • I updated my answer to show you how to loop over schema and convert it into a new string and put it into a new map Jan 22, 2019 at 17:41
  • I don't think I'm understanding what you're trying to show me. I added in the loop to convert to a string, changed the reference from fieldNames (this is a list) in my original post to fieldMap, and now in addition to "aura enabled methods do not support return type of Map" I'm getting "illegal conversion from Map to Map"
    – Shawn A
    Jan 22, 2019 at 18:04
  • Aura Enabled methods definitely do support returning Maps, so I'm guessing the error is originating elsewhere. Update you're orginal post with the updated code and I will take a look Jan 22, 2019 at 19:23

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .