├── .gitignore ├── src ├── classes │ ├── SDLSLookupComponentDemo.cls │ ├── SDLSLookupComponentDemo.cls-meta.xml │ ├── SLDSDynamicLookupController.cls-meta.xml │ ├── SLDSDynamicLookupControllerTest.cls-meta.xml │ ├── SLDSLookupComponentDemoController.cls-meta.xml │ ├── SLDSLookupComponentDemoControllerTest.cls-meta.xml │ ├── SLDSLookupComponentDemoControllerTest.cls │ ├── SLDSLookupComponentDemoController.cls │ ├── SLDSDynamicLookupControllerTest.cls │ └── SLDSDynamicLookupController.cls ├── staticresources │ ├── SLDS.resource │ ├── SLDS.resource-meta.xml │ ├── SLDSDynamicLookupScript.resource-meta.xml │ └── SLDSDynamicLookupScript.resource ├── tabs │ └── SLDS_Dynamic_Lookup_Demo.tab ├── components │ ├── SLDSDynamicLookup.component-meta.xml │ └── SLDSDynamicLookup.component ├── applications │ └── SLDS_Dynamic_Lookup.app ├── pages │ ├── SDLSLookupComponentDemo.page-meta.xml │ └── SDLSLookupComponentDemo.page └── package.xml ├── images ├── Demo1.png ├── Demo2.png ├── Demo3.png └── Demo4.png ├── .playground └── play.json ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | config/* 2 | debug/* 3 | *.sublime-* 4 | .history 5 | .playground/*.zip -------------------------------------------------------------------------------- /src/classes/SDLSLookupComponentDemo.cls: -------------------------------------------------------------------------------- 1 | public class SDLSLookupComponentDemo { 2 | 3 | } -------------------------------------------------------------------------------- /images/Demo1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkatney/SLDS-Dynamic-Lookup-Component/HEAD/images/Demo1.png -------------------------------------------------------------------------------- /images/Demo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkatney/SLDS-Dynamic-Lookup-Component/HEAD/images/Demo2.png -------------------------------------------------------------------------------- /images/Demo3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkatney/SLDS-Dynamic-Lookup-Component/HEAD/images/Demo3.png -------------------------------------------------------------------------------- /images/Demo4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkatney/SLDS-Dynamic-Lookup-Component/HEAD/images/Demo4.png -------------------------------------------------------------------------------- /src/staticresources/SLDS.resource: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkatney/SLDS-Dynamic-Lookup-Component/HEAD/src/staticresources/SLDS.resource -------------------------------------------------------------------------------- /.playground/play.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "SLDS Dynamic Lookup Component", 3 | "url": "slds-dynamic-lookup-component", 4 | "id": "2", 5 | "apiversion": "45.0" 6 | } -------------------------------------------------------------------------------- /src/classes/SDLSLookupComponentDemo.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 35.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /src/classes/SLDSDynamicLookupController.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 35.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /src/classes/SLDSDynamicLookupControllerTest.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 35.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /src/classes/SLDSLookupComponentDemoController.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 35.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /src/classes/SLDSLookupComponentDemoControllerTest.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 35.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /src/staticresources/SLDS.resource-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Public 4 | application/zip 5 | 6 | -------------------------------------------------------------------------------- /src/tabs/SLDS_Dynamic_Lookup_Demo.tab: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | false 5 | Custom37: Bridge 6 | SDLSLookupComponentDemo 7 | 8 | -------------------------------------------------------------------------------- /src/staticresources/SLDSDynamicLookupScript.resource-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Public 4 | text/javascript 5 | Script to work with SLDS dynamic component & support multiple components on page 6 | 7 | -------------------------------------------------------------------------------- /src/components/SLDSDynamicLookup.component-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 35.0 4 | 5 | 6 | 1 7 | 7 8 | sf_com_apps 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/applications/SLDS_Dynamic_Lookup.app: -------------------------------------------------------------------------------- 1 | 2 | 3 | SLDS_Dynamic_Lookup_Demo 4 | A component that can be used in Salesforce Lightning Design System VF pages 5 | Large 6 | 7 | SLDS_Dynamic_Lookup_Demo 8 | 9 | -------------------------------------------------------------------------------- /src/classes/SLDSLookupComponentDemoControllerTest.cls: -------------------------------------------------------------------------------- 1 | @isTest 2 | public class SLDSLookupComponentDemoControllerTest { 3 | public static testmethod void createRecordTest(){ 4 | SLDSLookupComponentDemoController controller = new SLDSLookupComponentDemoController(); 5 | controller.con.Firstname = 'Test'; 6 | controller.con.Lastname = 'SLDS Demo'; 7 | 8 | Test.startTest(); 9 | controller.createRecord(); 10 | Test.stopTest(); 11 | } 12 | } -------------------------------------------------------------------------------- /src/pages/SDLSLookupComponentDemo.page-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 35.0 4 | false 5 | false 6 | 7 | 8 | 1 9 | 7 10 | sf_com_apps 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/classes/SLDSLookupComponentDemoController.cls: -------------------------------------------------------------------------------- 1 | public class SLDSLookupComponentDemoController { 2 | 3 | public contact con{get;set;} 4 | public String oppId{get;set;} 5 | 6 | /** 7 | * Constructor 8 | **/ 9 | public SLDSLookupComponentDemoController(){ 10 | con = new Contact(AccountId = '00128000006QbVK', OwnerId = '00528000000MB72'); 11 | } 12 | 13 | /** 14 | * Method to create a record 15 | **/ 16 | public pagereference createRecord(){ 17 | insert con; 18 | return new pagereference('/'+con.Id); 19 | } 20 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Lakshay Katney 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SDLSLookupComponentDemo 5 | SLDSDynamicLookupController 6 | SLDSDynamicLookupControllerTest 7 | SLDSLookupComponentDemoController 8 | SLDSLookupComponentDemoControllerTest 9 | ApexClass 10 | 11 | 12 | SLDSDynamicLookup 13 | ApexComponent 14 | 15 | 16 | SDLSLookupComponentDemo 17 | ApexPage 18 | 19 | 20 | SLDS_Dynamic_Lookup 21 | CustomApplication 22 | 23 | 24 | SLDS_Dynamic_Lookup_Demo 25 | CustomTab 26 | 27 | 28 | SLDS 29 | SLDSDynamicLookupScript 30 | StaticResource 31 | 32 | 39.0 33 | 34 | -------------------------------------------------------------------------------- /src/classes/SLDSDynamicLookupControllerTest.cls: -------------------------------------------------------------------------------- 1 | @isTest 2 | private class SLDSDynamicLookupControllerTest { 3 | 4 | private static String USERNAME = 'SLDSDemoUser@lkatney.com'; 5 | 6 | private static testMethod void generateObjectLabelPluralTest() { 7 | SLDSDynamicLookupController controller = new SLDSDynamicLookupController(); 8 | controller.objectName = 'Account'; 9 | System.assertEquals('Accounts', controller.objectLabelPlural); 10 | } 11 | 12 | private static testMethod void generateUniqueComponentIdTest() { 13 | SLDSDynamicLookupController controller = new SLDSDynamicLookupController(); 14 | controller.Label = 'Set Account'; 15 | System.assertEquals('setaccount', controller.uniqueComponentId); 16 | } 17 | 18 | private static testmethod void searchTest(){ 19 | setupUser(); 20 | List lst = SLDSDynamicLookupController.search('User', 'Username,Name', 'Name(Username)', 'field->smallPhotoUrl', 'SLDS', null); 21 | System.assertEquals(1, lst.size()); 22 | } 23 | 24 | private static testmethod void loadComponentTest(){ 25 | User u = setupUser(); 26 | SLDSDynamicLookupController controller = new SLDSDynamicLookupController(); 27 | 28 | Test.startTest(); 29 | controller.objectName = 'User'; 30 | controller.fieldApiNames = 'Username,Name'; 31 | controller.displayPattern = 'Name(Username)'; 32 | controller.photoValue = 'field->smallPhotoUrl'; 33 | controller.setField = u.Id; 34 | Test.stopTest(); 35 | 36 | System.assertNotEquals(null, controller.displayValue); 37 | System.assertNotEquals(null, controller.photoUrl); 38 | 39 | } 40 | 41 | private static testMethod User setupUser() { 42 | Profile p = [SELECT Id FROM Profile WHERE Name='System Administrator']; 43 | User u = new User( Alias = 'standt', Email=USERNAME, 44 | EmailEncodingKey='UTF-8', LastName='Testing', LanguageLocaleKey='en_US', 45 | LocaleSidKey='en_US', ProfileId = p.Id, 46 | TimeZoneSidKey='America/Los_Angeles', UserName=USERNAME 47 | ); 48 | insert u; 49 | return u; 50 | } 51 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SLDS-Dynamic-Lookup-Component 2 | A package with a component that can be easily used to create lookup fields on VF page using Salesforce Lightning Design System(SLDS) 3 | 4 | Author [Lakshay Katney](http://blog.lkatney.com/about/) 5 | 6 | ## Setup 7 | 1. This repo is ready to deploy package in any Salesforce organization. Use any metadata tool to deploy it 8 | 2. There is an unmanaged version of this package too. Use below links to install it 9 | **[Sandbox](https://test.salesforce.com/packaging/installPackage.apexp?p0=04t280000003LDx)** 10 | **[Production/Developer](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t280000003LDx)** 11 | 12 | ## Usage 13 | On VF page, just add a static resource and component with appropriare attributes 14 | 15 | **Static Resource** 16 | ``` 17 | 18 | ``` 19 | 20 | **Component Usage** 21 | ``` 22 | 23 | ``` 24 | 25 | ## Attributes Usage 26 | 27 | Attribute | Requirement | Description 28 | :--------------------------:|:------------:|:-------------------------------- 29 | **SLDSResourceName** | Required | Attribute in which name of your static resource to be passed which contains Salesforce Lightning Design System(SLDS) 30 | **ObjectApiName** | Required | Api name of component on which search should happen. 31 | **DisplayFieldApiNames** | Required | Attribute to get fields Api Names whose value needs to be displayed while searching. These are seperated by comma. For example : 'firstname,lastname' 32 | **LabelName** | Required | Attribute to display label along with custom lookup field made by this component 33 | **SetValueToField** | Required | Attribute that will tell where to put selected value. Also populates the default value if field has value. 34 | **DisplayFieldsPattern** | Optional | Attribute to get pattern to display value.You can combine two fields with pattern. For example : 'firstname - lastname'. By default it will take pattern as comma seperated fields 35 | **photo** | Optional | Attribute that will tell if photo needs to be added to records while searching. For fields to be used, pattern should be 'field->fieldAPiName'. For url, pattern should be 'url->pathofimage' 36 | **FilterOn** | Optional | Attribute that will filter the list of records in results 37 | **RenderOnComplete** | Optional | Attribute that will run an action function/javascript on complete 38 | 39 | 40 | ## Screenshots 41 | 42 | ![Demo](/images/Demo1.png) 43 | ![Demo](/images/Demo2.png) 44 | ![Demo](/images/Demo3.png) 45 | ![Demo](/images/Demo4.png) 46 | 47 | ## Versions 48 | 49 | ### Version 1.4 50 | Introduction of dependent lookups 51 | Allow filters on lookups on basis of parent lookup 52 | 53 | ### Version 1.3 54 | ##### Improvements 55 | Allow default values to show if passed 56 | 57 | ### Version 1.2 58 | First version to add lookup fields in SLDS styling on Visual force pages 59 | 60 | 61 | -------------------------------------------------------------------------------- /src/pages/SDLSLookupComponentDemo.page: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Salesforce Lightning Design System Trailhead Module 7 | 8 | 13 | 14 | 15 | 16 | 17 | 18 |
19 |
20 | 21 |
SLDS Dynamic Lookup Demo
22 | 23 |
Create a contact
24 | 25 | 26 | 27 |
28 | 29 | 30 |
31 | 32 |
33 | 34 |
35 |
36 | 37 |
38 | 39 |
40 | 41 |
42 |
43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 |
57 | Submit 58 |
59 | 60 | 61 | 62 |
63 |
64 | 65 |
66 |
67 | 68 | 69 | 70 | 71 | 72 |
-------------------------------------------------------------------------------- /src/staticresources/SLDSDynamicLookupScript.resource: -------------------------------------------------------------------------------- 1 | //setup before functions 2 | var typingTimer; //timer identifier 3 | var doneTypingInterval = 500; 4 | 5 | /** 6 | * Method to fire once user stop writing 7 | */ 8 | function keyPressedOnLookup(componentId, objectName, fieldNames, fieldsPattern, photo, objectPluralName, queryFilters, remoteMethod){ 9 | clearTimeout(typingTimer); 10 | var selector = '#'+componentId; 11 | if (document.querySelector(selector+" #lookup").value) { 12 | typingTimer = setTimeout(startSearch(componentId, objectName, fieldNames, fieldsPattern, photo, objectPluralName, queryFilters, remoteMethod), doneTypingInterval); 13 | }else{ 14 | var searchText = document.querySelector(selector+" #lookup"); 15 | var lstBox = document.querySelector(selector+" #list-box"); 16 | lstBox.style.display = 'none'; 17 | } 18 | } 19 | 20 | /** 21 | * Function to get users from servers to display for Reviewers 22 | */ 23 | function startSearch(componentId, objectName, fieldNames, fieldsPattern, photo, objectPluralName, queryFilters, remoteMethod) { 24 | var selector = '#'+componentId; 25 | showLoader(componentId); 26 | var searchText = document.querySelector(selector+" #lookup"); 27 | if(queryFilters === '' || queryFilters.length === 0){ 28 | queryFilters = null; 29 | } 30 | Visualforce.remoting.Manager.invokeAction(remoteMethod, 31 | objectName, fieldNames, fieldsPattern, photo, searchText.value, null, queryFilters, 32 | function(result, event){ 33 | if (event.status) { 34 | var lstBox = document.querySelector(selector+" #list-box"); 35 | lstBox.style.display = 'block'; 36 | 37 | var recordLst = document.querySelector(selector+" #record-list"); 38 | recordLst.innerHTML = ''; 39 | for(var i = 0; i < result.length ; i++){ 40 | var record = result[i]; 41 | recordLst.appendChild(createRecordLi(componentId,record)); 42 | } 43 | document.querySelector(selector+" #search-text-info").innerHTML = searchText.value + ' in '+objectPluralName+' - '+ result.length + ' results found'; 44 | } else if (event.type === 'exception') { 45 | console.log(event.message); 46 | console.log(event.where); 47 | } else { 48 | console.log(event.message); 49 | } 50 | hideLoader(componentId); 51 | }, 52 | {escape: true} 53 | ); 54 | } 55 | 56 | /** 57 | * Create li for every record to display 58 | * @param user 59 | * @return li 60 | */ 61 | function createRecordLi(componentId,record){ 62 | var id = record.recordId; 63 | var displayName = record.displayValue; 64 | var photoUrl = record.photoUrl; 65 | var li = document.createElement("li"); 66 | li.setAttribute("class", "slds-lookup__item"); 67 | li.setAttribute("onclick", "select('"+componentId+"', '"+displayName+"', '"+photoUrl+"', '"+id+"')"); 68 | var inner = ''; 69 | if(photoUrl){ 70 | inner += ''; 71 | } 72 | inner += displayName; 73 | inner += ''; 74 | 75 | li.innerHTML = inner; 76 | return li; 77 | } 78 | 79 | /** 80 | * Select record from list 81 | * @param {[type]} displayName [description] 82 | * @param {[type]} photoUrl [description] 83 | * @param {[type]} id [description] 84 | * @return {[type]} [description] 85 | */ 86 | function select(componentId, name,photoUrl,id){ 87 | var selector = '#'+componentId; 88 | showLoader(componentId); 89 | document.querySelector(selector+" #selected-name").innerHTML = name; 90 | if(photoUrl != 'undefined' && photoUrl != '' && photoUrl != null){ 91 | document.querySelector(selector+" #select-image").style.display = 'inline'; 92 | document.querySelector(selector+" #select-image").setAttribute("src", photoUrl); 93 | }else{ 94 | document.querySelector(selector+" #select-image").style.display = 'none'; 95 | } 96 | eval(componentId+"setOwnerId('"+id+"')"); 97 | } 98 | 99 | /** 100 | * User selected function 101 | * @return {[type]} [description] 102 | */ 103 | function recordSelected(componentId, renderOnComplete){ 104 | var selector = '#'+componentId; 105 | if(document.querySelector(selector+" #selected-record").style.display == 'none'){ 106 | document.querySelector(selector+" #selected-record").style.display = 'block'; 107 | document.querySelector(selector+" #input-text").style.display = 'none'; 108 | document.querySelector(selector+" #lookup").value = ''; 109 | var lstBox = document.querySelector(selector+" #list-box"); 110 | lstBox.style.display = 'none'; 111 | }else{ 112 | document.querySelector(selector+" #input-text").style.display = 'block'; 113 | document.querySelector(selector+" #selected-record").style.display = 'none'; 114 | } 115 | if(renderOnComplete && renderOnComplete.length > 0){ 116 | eval(renderOnComplete + '()'); 117 | } 118 | hideLoader(componentId); 119 | } 120 | 121 | /** 122 | * remove selected record 123 | * @return {[type]} [description] 124 | */ 125 | function removeRecord(componentId){ 126 | var selector = '#'+componentId; 127 | eval(componentId+"setOwnerId(null)"); 128 | } 129 | 130 | function showLoader(componentId){ 131 | var selector = '#'+componentId; 132 | document.querySelector(selector+" #loader").style.display = 'block'; 133 | } 134 | 135 | function hideLoader(componentId){ 136 | var selector = '#'+componentId; 137 | document.querySelector(selector+" #loader").style.display = 'none'; 138 | } -------------------------------------------------------------------------------- /src/components/SLDSDynamicLookup.component: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 10 | 13 | 16 | 19 | 22 | 25 | 28 | 31 | 32 | 33 |
34 | 40 | 41 | 42 | 43 | 44 |
45 |
46 | 47 |
48 | 49 | 50 | 60 | 61 | 62 |
63 | 64 | 67 |
68 |
69 |
70 | 71 | 72 | 80 |
81 |
82 |
-------------------------------------------------------------------------------- /src/classes/SLDSDynamicLookupController.cls: -------------------------------------------------------------------------------- 1 | public class SLDSDynamicLookupController { 2 | /* 3 | * public variables 4 | **/ 5 | public String objectName{get; 6 | set{ 7 | if(objectName != value){ 8 | objectName = value; 9 | objectLabelPlural = Schema.getGlobalDescribe().get(ObjectName).getDescribe(). getLabelPlural(); 10 | } 11 | } 12 | 13 | } 14 | 15 | public String label{ 16 | get; 17 | set{ 18 | label = value; 19 | uniqueComponentId = label.replace(' ', '').toLowerCase(); 20 | } 21 | } 22 | 23 | public String setField{ 24 | get; 25 | set{ 26 | if(String.isNotBlank(value)){ 27 | setField = value; 28 | if(String.isBlank(photoValue)){ 29 | photoValue = ''; 30 | } 31 | 32 | List results = search(objectName, fieldApiNames, displayPattern, photoValue, null, value, filters); 33 | 34 | if(!results.isEmpty()){ 35 | displayValue = results[0].displayValue; 36 | if(String.isNotBlank(results[0].photoUrl)){ 37 | photoUrl = results[0].photoUrl; 38 | }else{ 39 | photoUrl = ''; 40 | } 41 | } 42 | } 43 | } 44 | } 45 | 46 | public String uniqueComponentId{get;set;} 47 | public String objectLabelPlural{get;set;} 48 | public String displayValue{get;set;} 49 | public String photoUrl{get;set;} 50 | public String fieldApiNames{get;set;} 51 | public String displayPattern{get;set;} 52 | public String photoValue{get;set;} 53 | public String filters{get;set;} 54 | 55 | /** 56 | * Remote action method to send list of records 57 | * @param searchText 58 | * @return List 59 | */ 60 | @RemoteAction 61 | public static List search(String objectName, String displayFieldNames, String fieldsPattern, String photoValue,String searchText, String recordId, String queryFilters) { 62 | String query; 63 | List displayFieldNamesLst; 64 | String photoFieldName; 65 | List results = new List(); 66 | String finalQuery; 67 | String photoToDisplay; 68 | 69 | if(String.isBlank(fieldsPattern)){ 70 | fieldsPattern = displayFieldNames; 71 | } 72 | 73 | //prepare a where clause 74 | displayFieldNamesLst = displayFieldNames.split(','); 75 | String whereClause = ''; 76 | 77 | if(String.isBlank(recordId)){ 78 | for(String fieldName : displayFieldNamesLst){ 79 | whereClause += String.isBlank(whereClause) ? ' WHERE ' + fieldName + ' LIKE \'%{text}%\'' : ' OR ' + fieldName + ' LIKE \'%{text}%\''; 80 | } 81 | }else{ 82 | whereClause += ' WHERE Id =: recordId'; 83 | } 84 | 85 | String filtersClause = createWhereClauseFromFilters(queryFilters); 86 | 87 | if(String.isNotBlank(filtersClause)){ 88 | whereClause += ' AND ' + filtersClause; 89 | } 90 | 91 | //add Id field to field names if necessary 92 | if(!displayFieldNames.toLowerCase().contains('id')){ 93 | displayFieldNames += ', Id'; 94 | } 95 | 96 | //add photo field if not added 97 | if(photoValue.toLowerCase().contains('field')){ 98 | List photoValueLst = photoValue.split('->'); 99 | if(photoValueLst.size() > 1 && !displayFieldNames.toLowerCase().contains(photoValueLst[1].toLowerCase())){ 100 | photoFieldName = photoValueLst[1]; 101 | displayFieldNames += ', '+photoValueLst[1]; 102 | } 103 | }else if(photoValue.toLowerCase().contains('url')){ 104 | List photoValueLst = photoValue.split('->'); 105 | if(photoValueLst.size() > 1){ 106 | photoToDisplay = photoValueLst[1]; 107 | } 108 | } 109 | 110 | query = 'SELECT ' + displayFieldNames + ' FROM ' + objectName + whereClause; 111 | 112 | if(String.isBlank(recordId)){ 113 | finalQuery = query.replace('{text}', searchText); 114 | }else{ 115 | finalQuery = query; 116 | } 117 | 118 | System.debug(':::QUERY:::' + finalQuery); 119 | 120 | for(Sobject sobj : database.query(finalQuery)){ 121 | String displayValue = fieldsPattern; 122 | for(String fieldName : displayFieldNamesLst){ 123 | String fieldValue = sobj.get(fieldName) == null ? '' : String.valueOf(sobj.get(fieldName)); 124 | displayValue = displayValue.replace(fieldName, fieldValue); 125 | if(String.isNotBlank(photoFieldName) && sobj.get(photoFieldName) != null){ 126 | photoToDisplay = String.valueOf(sobj.get(photoFieldName)); 127 | } 128 | } 129 | results.add(new Wrapper(String.valueOf(sobj.get('Id')), displayValue, photoToDisplay)); 130 | } 131 | return results; 132 | } 133 | 134 | private static String createWhereClauseFromFilters(String queryFilters){ 135 | String filtersClause; 136 | if(queryFilters != null && String.isNotBlank(queryFilters)){ 137 | String replacedFilters = queryFilters.replace('\\', ''); 138 | filtersClause = String.join(replacedFilters.split(','), ' AND '); 139 | } 140 | return filtersClause; 141 | } 142 | 143 | /************************************************************************* 144 | ******************************* WRAPPER ************************************** 145 | ****************************************************************************/ 146 | public class Wrapper{ 147 | public Id recordId{get;set;} 148 | public String displayValue{get;set;} 149 | public String photoUrl{get;set;} 150 | public Wrapper(Id recordId, String displayValue, String photoUrl){ 151 | this.recordId = recordId; 152 | this.displayValue = displayValue; 153 | this.photoUrl = photoUrl; 154 | } 155 | } 156 | } --------------------------------------------------------------------------------