項目中,我們有時候會需要實現自動聯想功能,比如我們想輸入用戶或者聯系人名稱,去聯想出系統中有的相關的用戶和聯系人,當點擊以后獲取相關的郵箱或者其他信息等等。這種情況下可以使用jquery ui中的autoComplete實現。
此篇需求為在輸入框中輸入檢索詞對數據庫中User表和Contact表的Name字段進行檢索,符合條件的放在聯想列表中,當用戶選擇相應的名稱后,輸入框中顯示此名稱對應的郵箱地址。
實現此功能可以整體分成三步:
1.通過輸入內容檢索相關表中符合條件的數據;
2.對檢索的數據進行去重以及封裝;
3.前台綁定autoComplete實現自動聯想功能。
一.通過輸入內容檢索相關表中符合條件的數據
因為要對兩個表進行操作,使用SOQL需要對兩個表進行查詢,並對搜索結果進行拼接,這種方式使用SOQL只能對每個字符進行like操作。比如輸入中行大連,使用SOQL需要拆分成 where name like '%中%行%大%連%'。此種檢索搜索出來的結果可能會搜索出用戶不想搜索出來的結果,比如 ‘行連大中’。而且對多個表操作推薦使用SOSL,所以此處使用SOSL進行檢索操作。
SOSL的操作以及檢索封裝可以參看:salesforce零基礎學習(七十五)淺談SOSL(Salesforce Object Search Language),此篇使用封裝的方法作為Util。
二.對檢索的數據進行去重以及封裝
對於搜索結果,我們需要三部分內容:
- 搜索的數據中對象的名稱:objName;
- 搜索的數據類型,屬於User還是Contact: objType;
- 搜索的數據中對象的郵箱:objEmail
所以我們封裝一下這個結果集的類,包含三個字段。因為我們最終需要的是用戶/聯系人郵箱,如果用戶/聯系人名稱和用戶/聯系人郵箱完全相同,則我們假定他們是相同的數據。所以我們重寫一下equals()和hashCode()方法,定義一下兩條數據相同的規則。定義后,可以先使用Set接受結果集進行去重,然后轉換成List進行結果返回。代碼如下:
1 public without sharing class AutoRetrieveController { 2 3 public String content{get;set;} 4 5 @RemoteAction 6 public static List<ObjWrapper> retrieveUsersOrContacts(String name) { 7 //返回的結果集 8 List<ObjWrapper> results; 9 //用於去重的set,去除名稱和email相同的數據 10 Set<ObjWrapper> resultSet = new Set<ObjWrapper>(); 11 //封裝數據查詢曾 12 SOSLController.RetrieveWrapper wrapper = new SOSLController.RetrieveWrapper(); 13 wrapper.retrieveKeyword = name; 14 wrapper.searchGroup = 'NAME FIELDS'; 15 wrapper.objName2FieldsMap = new Map<String,List<String>>(); 16 List<String> userFields = new List<String>{'Name','Email'}; 17 List<String> contactFields = new List<String>{'Name','Email'}; 18 wrapper.objName2FieldsMap.put('user',userFields); 19 wrapper.objName2FieldsMap.put('contact',contactFields); 20 //獲取結果顯示列表 21 List<SOSLController.SearchResultWrapper> searchResultList = SOSLController.search(wrapper); 22 //迭代,數據轉換以及去重處理 23 if(searchResultList!= null && searchResultList.size() > 0) { 24 for(SOSLController.SearchResultWrapper temp : searchResultList) { 25 ObjWrapper tempWrapper = new ObjWrapper(); 26 tempWrapper.objType = temp.objName; 27 Map<String,Object> fieldsMap = temp.objFieldName2Value; 28 if(fieldsMap.get('Name') != null) { 29 tempWrapper.objName = (String)fieldsMap.get('Name'); 30 } 31 if(fieldsMap.get('Email') != null) { 32 tempWrapper.objEmail = (String)fieldsMap.get('Email'); 33 } 34 resultSet.add(tempWrapper); 35 } 36 } 37 if(resultSet.size() > 0) { 38 results = new List<ObjWrapper>(resultSet); 39 } else { 40 results = new List<ObjWrapper>(); 41 } 42 return results; 43 } 44 45 public class ObjWrapper { 46 public String objName{get;set;} 47 public String objEmail{get;set;} 48 public String objType{get;set;} 49 50 public Boolean equals(Object o){ 51 Boolean result = false; 52 if(o instanceof ObjWrapper) { 53 ObjWrapper obj = (ObjWrapper)o; 54 if(objEmail != null && objName != null) { 55 if(objEmail.equalsIgnoreCase(obj.objEmail) && objName.equalsIgnoreCase(obj.objName)) { 56 result = true; 57 } 58 } 59 60 } 61 return result; 62 } 63 64 public Integer hashCode() { 65 return 1; 66 } 67 } 68 }
三.前台綁定autoComplete實現自動聯想功能
使用jquery ui的autoComplete功能,需要下載jquery ui 的js以及css文件,頁面使用了jquery,所以也需要使用jquery的js文件。下載后壓縮成zip包,上傳到static resource便可以引用了。
此處為將三個文件放在了jquery的文件夾下,上傳了zip包名稱為JqueryUI。頁面代碼如下:
1 <apex:page controller="AutoRetrieveController"> 2 3 <apex:includeScript value="{!URLFOR($Resource.JqueryUI, 'jquery/jquery.js')}" /> 4 <apex:includeScript value="{!URLFOR($Resource.JqueryUI, 'jquery/jquery-ui.min.js')}" /> 5 <apex:stylesheet value="{!URLFOR($Resource.JqueryUI, 'jquery/jquery-ui.min.css')}" /> 6 <apex:form> 7 <apex:inputText id="content" value="{!content}" onmousedown="autoCompleteList()" styleClass="contentWidth"/> 8 </apex:form> 9 10 11 <script> 12 13 j$ = jQuery.noConflict(); 14 15 function autoCompleteList(){ 16 var contentDom = j$("input[id$=content]"); 17 if (contentDom.size() == 0) { 18 return ; 19 } 20 contentDom.autocomplete({ 21 minLength: 2, 22 autoFocus: true, 23 source: function(request, response) { 24 queryTerm = request.term; 25 console.log(queryTerm); 26 if(queryTerm != '') { 27 AutoRetrievController.retrieveUsersOrContacts( 28 queryTerm, 29 function(result, event) { 30 if (event.type == 'exception') { 31 } else { 32 sObjects = result; 33 if (0 == sObjects.length) { 34 response(null); 35 } else { 36 response(sObjects); 37 } 38 } 39 }); 40 } 41 }, 42 focus: function(event, ui) { 43 return false; 44 }, 45 46 select: function(event, ui) { 47 this.value = ui.item.objEmail; 48 return false; 49 }, 50 }).data("uiAutocomplete")._renderItem = function(ul, item) { 51 var entry = item.objName +'\t\t' + item.objType; 52 entry = entry.replace(queryTerm, "<b>" + queryTerm + "</b>"); 53 return j$( "<li></li>" ) 54 .data( "item.autocomplete", item ) 55 .append( "<a>" + entry + "</a>" ) 56 .appendTo( ul ); 57 }; 58 } 59 60 </script> 61 </apex:page>
效果展示:
總結:聯想功能在開發中還是比較常用的,autoComplete功能有好多相關的方法,可以去官網或者其他渠道了解相關方法進行UI的美化。篇中只是對基礎功能進行拋磚引玉。
還有好多功能點需要優化,比如對數據檢索沒有進行相關limit的限制,去重方法寫的過於簡單,沒有分別考慮null的處理等等。有興趣的小伙伴可以繼續完善。