项目中,我们有时候会需要实现自动联想功能,比如我们想输入用户或者联系人名称,去联想出系统中有的相关的用户和联系人,当点击以后获取相关的邮箱或者其他信息等等。这种情况下可以使用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。
二.对检索的数据进行去重以及封装
对于搜索结果,我们需要三部分内容:
所以我们封装一下这个结果集的类,包含三个字段。因为我们最终需要的是用户/联系人邮箱,如果用户/联系人名称和用户/联系人邮箱完全相同,则我们假定他们是相同的数据。所以我们重写一下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的处理等等。有兴趣的小伙伴可以继续完善。