├── .gitignore ├── LICENSE ├── README.md ├── images └── demo_picklist_select_component.png └── src ├── aura └── PicklistSelect │ ├── PicklistSelect.cmp │ ├── PicklistSelect.cmp-meta.xml │ ├── PicklistSelect.design │ ├── PicklistSelectController.js │ └── PicklistSelectHelper.js ├── classes ├── PicklistSelectController.cls ├── PicklistSelectController.cls-meta.xml ├── PicklistSelectControllerTest.cls └── PicklistSelectControllerTest.cls-meta.xml ├── flexipages └── Demo_PicklistSelect_Component.flexipage ├── package.xml └── tabs └── Demo_PicklistSelect_Component.tab /.gitignore: -------------------------------------------------------------------------------- 1 | config/ 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2017, Doug Ayers 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Lightning Picklist Field Select Component 2 | 3 | Lightning Component that renders `lightning:select` with options from an sobject picklist field. Ideally, this component shouldn't be needed but as of Winter '16 release the `force:inputField` component has a [bug that when used with picklist fields it renders disabled](https://success.salesforce.com/issues_view?id=a1p3A0000001BaTQAU). Disabled form fields are not conducive to users entering data. 4 | 5 | 6 | Deploy to Salesforce 8 | 9 | 10 | ![screenshot](images/demo_picklist_select_component.png) 11 | 12 | # Usage 13 | 14 | The simplest way is to use the component and specify `objectName` and `fieldName` required attributes: 15 | 16 | ``` 17 | 18 | ``` 19 | 20 | Since the standard [lightning:select](https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/aura_compref_lightning_select.htm) component is used by this component, most of the standard attributes are available to you as well: 21 | 22 | | Attribute | Description | Required? | 23 | |-----------|-------------|-----------| 24 | | objectName | API name of object | yes | 25 | | fieldName | API name of picklist field | yes | 26 | | label | Text that describes the desired select input. Default is the field's label. | no | 27 | | value | The value of the select, also used as the default value to select the right option during init. If no value is provided, the first option will be selected. | no | 28 | | class | A CSS class that will be applied to the outer element. This style is in addition to base classes associated with the component. | no 29 | | onblur | The action triggered when the element releases focus. | no | 30 | | onfocus | The action triggered when the element receives focus. | no | 31 | | onchange | The action triggered when a value attribute changes. | no | 32 | -------------------------------------------------------------------------------- /images/demo_picklist_select_component.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglascayers/sfdc-lightning-picklist-field-component/703a09a7d00080408ecff2b64634bf6471299007/images/demo_picklist_select_component.png -------------------------------------------------------------------------------- /src/aura/PicklistSelect/PicklistSelect.cmp: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/aura/PicklistSelect/PicklistSelect.cmp-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 38.0 4 | A Lightning Component Bundle 5 | 6 | -------------------------------------------------------------------------------- /src/aura/PicklistSelect/PicklistSelect.design: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/aura/PicklistSelect/PicklistSelectController.js: -------------------------------------------------------------------------------- 1 | ({ 2 | doInit : function(component, event, helper) { 3 | 4 | helper.callAction( component, 'c.getFieldLabel', { 5 | 'objectName' : component.get('v.objectName'), 6 | 'fieldName' : component.get('v.fieldName') 7 | }, function( data ) { 8 | component.set('v.label', data); 9 | }); 10 | 11 | helper.callAction( component, 'c.getPicklistOptions', { 12 | 'objectName' : component.get('v.objectName'), 13 | 'fieldName' : component.get('v.fieldName') 14 | }, function( data ) { 15 | component.set('v.options', data); 16 | }); 17 | 18 | } 19 | 20 | }) -------------------------------------------------------------------------------- /src/aura/PicklistSelect/PicklistSelectHelper.js: -------------------------------------------------------------------------------- 1 | ({ 2 | /** 3 | * actionName = the apex controller method to call (e.g. 'c.myMethod' ) 4 | * params = JSON object specifying action parameters (e.g. { 'x' : 42 } ) 5 | * successCallback = function to call when action completes (e.g. function( response ) { ... } ) 6 | * failureCallback = function to call when action fails (e.g. function( response ) { ... } ) 7 | */ 8 | callAction : function( component, actionName, params, successCallback, failureCallback ) { 9 | 10 | var action = component.get( actionName ); 11 | 12 | if ( params ) { 13 | action.setParams( params ); 14 | } 15 | 16 | action.setCallback( this, function( response ) { 17 | if ( component.isValid() && response.getState() === 'SUCCESS' ) { 18 | 19 | if ( successCallback ) { 20 | successCallback( response.getReturnValue() ); 21 | } 22 | 23 | } else { 24 | 25 | console.error( 'Error calling action "' + actionName + '" with state: ' + response.getState() ); 26 | 27 | if ( failureCallback ) { 28 | failureCallback( response.getError(), response.getState() ); 29 | } else { 30 | this.logActionErrors( component, response.getError() ); 31 | } 32 | 33 | } 34 | }); 35 | 36 | $A.enqueueAction( action ); 37 | 38 | }, 39 | 40 | logActionErrors : function( component, errors ) { 41 | if ( errors ) { 42 | for ( var index in errors ) { 43 | console.error( 'Error: ' + errors[index].message ); 44 | } 45 | } else { 46 | console.error( 'Unknown error' ); 47 | } 48 | } 49 | 50 | }) 51 | -------------------------------------------------------------------------------- /src/classes/PicklistSelectController.cls: -------------------------------------------------------------------------------- 1 | public with sharing class PicklistSelectController { 2 | 3 | /** 4 | * Given an API object and field name, returns the configured field label to display to users. 5 | */ 6 | @AuraEnabled 7 | public static String getFieldLabel( String objectName, String fieldName ) { 8 | 9 | System.debug( 'Getting field label: objectName=' + objectName + ', fieldName=' + fieldName ); 10 | 11 | String label = Schema.getGlobalDescribe().get( objectName ).getDescribe().fields.getMap().get( fieldName ).getDescribe().getLabel(); 12 | 13 | System.debug( 'label= ' + label ); 14 | 15 | return label; 16 | } 17 | 18 | /** 19 | * Given an API object and field name, returns list of the picklist values for use in select input. 20 | */ 21 | @AuraEnabled 22 | public static List getPicklistOptions( String objectName, String fieldName ) { 23 | 24 | System.debug( 'Getting picklist options: objectName=' + objectName + ', fieldName=' + fieldName ); 25 | 26 | List options = new List(); 27 | 28 | for ( PicklistEntry entry : Schema.getGlobalDescribe().get( objectName ).getDescribe().fields.getMap().get( fieldName ).getDescribe().getPicklistValues() ) { 29 | options.add( new PicklistOption( entry.getLabel(), entry.getValue() ) ); 30 | } 31 | 32 | System.debug( 'options=' + options ); 33 | 34 | return options; 35 | } 36 | 37 | /** 38 | * The system class PicklistEntry is not aura enabled so cannot be returned from @AuraEnabled method. 39 | * Workaround is to define our own class with aura enabled properties. 40 | */ 41 | public class PicklistOption { 42 | 43 | @AuraEnabled 44 | public String label { get; set; } 45 | 46 | @AuraEnabled 47 | public String value { get; set; } 48 | 49 | public PicklistOption( String label, String value ) { 50 | this.label = label; 51 | this.value = value; 52 | } 53 | 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/classes/PicklistSelectController.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 38.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /src/classes/PicklistSelectControllerTest.cls: -------------------------------------------------------------------------------- 1 | @isTest 2 | private class PicklistSelectControllerTest { 3 | 4 | @isTest 5 | static void test_get_field_label() { 6 | 7 | Test.startTest(); 8 | 9 | String fieldLabel = PicklistSelectController.getFieldLabel( 'Account', 'Type' ); 10 | 11 | Test.stopTest(); 12 | 13 | System.assertEquals( Account.Type.getDescribe().getLabel(), fieldLabel ); 14 | 15 | } 16 | 17 | @isTest 18 | static void test_get_picklist_values() { 19 | 20 | Test.startTest(); 21 | 22 | List options = PicklistSelectController.getPicklistOptions( 'Account', 'Type' ); 23 | 24 | Test.stopTest(); 25 | 26 | List values = Account.Type.getDescribe().getPicklistValues(); 27 | 28 | for ( Integer i = 0; i < options.size(); i++ ) { 29 | System.assertEquals( values[i].getLabel(), options[i].label ); 30 | System.assertEquals( values[i].getValue(), options[i].value ); 31 | } 32 | 33 | } 34 | 35 | } -------------------------------------------------------------------------------- /src/classes/PicklistSelectControllerTest.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 38.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /src/flexipages/Demo_PicklistSelect_Component.flexipage: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | fieldName 7 | Type 8 | 9 | 10 | objectName 11 | Account 12 | 13 | PicklistSelect 14 | 15 | 16 | 17 | fieldName 18 | Status 19 | 20 | 21 | objectName 22 | Lead 23 | 24 | PicklistSelect 25 | 26 | 27 | 28 | fieldName 29 | StageName 30 | 31 | 32 | objectName 33 | Opportunity 34 | 35 | PicklistSelect 36 | 37 | main 38 | Region 39 | 40 | Demo PicklistSelect Component 41 | flexipage:defaultAppHomeTemplate 42 | AppPage 43 | 44 | -------------------------------------------------------------------------------- /src/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | PicklistSelectController 5 | PicklistSelectControllerTest 6 | ApexClass 7 | 8 | 9 | PicklistSelect 10 | AuraDefinitionBundle 11 | 12 | 13 | Demo_PicklistSelect_Component 14 | CustomTab 15 | 16 | 17 | Demo_PicklistSelect_Component 18 | FlexiPage 19 | 20 | 38.0 21 | 22 | -------------------------------------------------------------------------------- /src/tabs/Demo_PicklistSelect_Component.tab: -------------------------------------------------------------------------------- 1 | 2 | 3 | Created by Lightning App Builder 4 | Demo_PicklistSelect_Component 5 | 6 | true 7 | Custom60: Umbrella 8 | 9 | --------------------------------------------------------------------------------