使用 JavaScript 为 SharePoint 2010/2013 实现多表单字段自动完成






4.93/5 (6投票s)
本文介绍如何使用 JavaScript 为 SharePoint 2010/2013 的多个表单字段实现自动完成功能。
介绍
有时填写表单会很麻烦,特别是对于有很多字段的表单。在本文中,我将介绍一种可以显著简化表单填写的方法。在我的例子中,我需要实现一个订单表单界面。实际上,它包含许多字段,我可以根据选择的客户预先填充,例如地址、邮政编码和账号。所有这些数据都已存储在一个名为“客户目录”的单独列表中。
最终需求可能看起来像这样
当用户在客户字段中开始键入时,我需要从“客户目录”中建议客户姓名列表。当用户从建议列表中选择客户时,我需要从“客户目录”中读取多个字段值,并填充订单表单中相应的字段。用户以后可以根据需要更正已填写的字段。
为了实现这样的功能,我过去一直使用 JavaScript,这次也不例外。这有很多原因:
- 它很好地符合 Office 365 的限制。
- 它可以轻松地从旧版 SharePoint 迁移。
- 无需缓慢部署 SharePoint 解决方案即可轻松调试。
- REST SharePoint 2013 API 或 SPServices 与服务器代码一样强大。
- 最后,我就是喜欢它。
在本文中,我将使用SPServices jQuery 插件与 SharePoint 服务进行通信。它适用于 SharePoint 2013 和 SharePoint 2010。我还将使用jQuery UI Autocomplete 插件来实现建议功能。
plumFormAutocomplete 插件既适用于单个字段,也适用于多个字段。该插件仅支持文本字段。
插件的实际效果如下所示
如何使用 plumFormAutocomplete jQuery 插件
您可以直接使用此插件,无需查看代码。首先,我将描述如何使用它,然后如果您仍然感兴趣,可以查看插件的实现。
必备组件
如果您还没有 jQuery、jQuery UI 或 SPServices,可以从官方网站下载最新版本。为方便教程,我假设下载的文件和文件夹名称如下:
- jquery.min.js
- jquery.SPervices.min.js
- jquery-ui-1.10.3.custom.min.js
- jquery-ui-1.10.3.custom.min.css
- jQuery UI 的 CSS 文件夹
我还假设您已从本文的源代码下载了jquery.plumFormAutocomplete.js(源代码下载链接)。
将jquery.min.js、jquery.SPServices.min.js、jquery-ui-1.10.3.custom.min.js 和jquery.plumFormAutocomplete.js 文件上传到您网站集内的样式库 (Style Library)。您还需要上传与jquery-ui-1.10.3.custom.min.js 位于同一文件夹的 jQuery UI CSS 样式。然后,打开将使用自动完成插件的新建或编辑表单,并将 js 和 CSS 链接添加到占位符PlaceHolderAdditionalPageHead。您可以使用以下代码片段:
<SharePoint:ScriptLink runat="server"
Name="~SiteCollection/Style Library/jquery.min.js" Language="javascript"/>
<SharePoint:ScriptLink runat="server"
Name="~SiteCollection/Style Library/jquery.SPServices.min.js" Language="javascript"/>
<SharePoint:ScriptLink runat="server"
Name="~SiteCollection/Style Library/jquery-ui-1.10.3/jquery-ui-1.10.3.custom.
min.js" Language="javascript"/>
<SharePoint:ScriptLink runat="server"
Name="~SiteCollection/Style Library/jquery.plumFormAutocomplete.js" Language="javascript"/>
<SharePoint:CSSRegistration name="<% $SPUrl:~SiteCollection/Style Library/
jquery-ui-1.10.3/css/smoothness/jquery-ui-1.10.3.custom.min.css%>" runat="server"/>
配置并调用插件
现在您可以配置并调用插件了。在我的例子中,插件调用如下:
//get control for autocomplete field
var fieldControl = $.getFieldControl('Title');
//call autocomplete plugin for field control
fieldControl.plumFormAutocomplete({
sourceList: 'Customers directory',
sourceMatchField: 'Title',
labelFields: ['Title', 'ZIPCode'],
labelSeparator: ', ',
fillConcatenatedLabel: false,
fieldsMapping: [{sourceField: 'Address', targetField: 'CustAddress'},
{sourceField: 'AccountNumber', targetField: 'CustAccountNumber'},
{sourceField: 'ZIPCode', targetField: 'CustZIPCode'}]
});
您可以将插件调用包装在 jQuery $(document).ready() 函数中,以确保代码在页面加载后执行。
让我们更详细地看一下这个代码示例。代码分为两部分:
- 获取自动完成字段的控件
- 为字段控件调用自动完成插件
第一步,您需要为 getFieldControl 函数指定自动完成字段的内部名称。在我的例子中是“Title”。
第二步,您需要为获取到的自动完成字段调用插件并配置插件选项。插件选项结构为一个对象,就像任何 jQuery 插件选项一样。
插件选项
- sourceList - 源列表的名称或 GUID,将从中获取建议。在我的例子中是“Customers directory”。
- sourceMatchField - 源列表中的字段内部名称。此字段将用于查找与自动完成关键字匹配的列表项。
- labelFields - 一个可选参数,您可以指定源列表字段内部名称数组。这些字段的所有值将用 labelSeparator 连接,并显示在自动完成建议中,形成一个单一字符串,例如:Value1, Value2, ..., ValueN。
- labelSeparator - 一个可选参数,它是用于连接 labelFields 的分隔符,例如,可以是逗号加空格(', ')。
- fillConcatenatedLabel - 一个可选参数,如果需要用所有连接的 labelFields 值填充自动完成文本框,则设置为 true;如果只需要用单个字段值填充自动完成文本框,则设置为 false。
- fieldsMapping - 一个可选参数,它是一个字段映射对象的数组。每个对象声明从源列表字段到目标列表字段的映射。在我的例子中,源字段和目标字段的名称是相同的。例如,“Customers directory”中的 Address 和 Orders 列表中的 Address。
映射对象的语法如下:
{sourceField: 'Internal name of source field', targetField: 'Internal name of target field'}
注意:您只需指定非可选参数,插件即可正常工作。此插件也可以很好地用于单个字段自动完成,只需不填写可选参数即可。
不带可选参数的插件配置可能如下所示:
fieldControl.plumFormAutocomplete({
sourceList: 'Customers directory',
sourceMatchField: 'Title'
});
插件的内部实现
让我们看完整的插件源代码。您可以 在此处 下载。
代码中有三个主要部分:
- 获取文本字段输入。
- 应用 jQueryUIi 自动完成插件和 SPServices 以获取建议。
- 实现辅助函数。
为了获取字段输入,我使用了 jQuery 选择器和简单的正则表达式。不幸的是,SharePoint 没有提供任何方法来通过 JavaScript 获取字段控件,它只在 HTML 注释中以以下格式存储字段的内部名称:
<!-- FieldName="Title"
FieldInternalName="Title"
FieldType="SPFieldText"
-->
因此,我必须对其进行解析才能找到我需要的控件。最终的函数已添加到 jQuery 中:
//function gets text field control by internal name
$.getFieldControl = function (fieldInternalName) {
var regexStr = 'FieldInternalName="' + fieldInternalName + '"'
var regex = new RegExp(regexStr, 'i');
var fieldCell = $('td.ms-formbody').filter(function () {
return (regex).test($(this).html())
});
return $(fieldCell.find('input')[0]);
}
在下一步中,我应用了 jQuery UI 自动完成插件,并实现了 source 和 select 插件函数。Source 函数使用 SPServices 和 CAML 调用源列表以获取建议。当找到建议时,我将所有映射的字段值存储在 autcomplete 对象中。
source: function (request, response) {
var autocompleteVals = [];
var k = 0;
$().SPServices({
operation: "GetListItems",
async: false,
listName: options.sourceList,
CAMLViewFields: getViewFields(options.fieldsMapping),
CAMLQuery: getCamlQuery(options.sourceMatchField, request.term),
completefunc: function (xData, Status) {
$(xData.responseXML).SPFilterNode("z:row").each(function () {
var queryResult = this;
var fieldsValues = getFieldsValues(options.fieldsMapping, queryResult);
var labelText = getLabelText(fieldsValues);
autocompleteVals[k] = {
label: labelText,
value: options.fillConcatenatedLabel ? labelText :
extractFieldValue(fieldsValues, options.sourceMatchField),
fieldsValues: fieldsValues
};
k++;
function getLabelText(fieldValues){
var result = '';
if(options.labelFields){
for(i = 0; i < options.labelFields.length; i++)
{
var fieldName = options.labelFields[i];
var fieldVal = extractFieldValue(fieldValues, fieldName);
if(fieldVal != ''){
if(i > 0){
result += options.labelSeparator;
}
result += fieldVal;
}
}
} else {
result += extractFieldValue(fieldValues, options.sourceMatchField);
}
return result;
}
});
response(autocompleteVals);
}
});
}
Select 函数根据从源列表匹配的项,填充映射字段中的值。它读取存储在 ui.item 中的值,并根据所选的建议填充相应的字段。
select: function (event, ui) {
//Fill all depended fields
$.each(ui.item.fieldsValues, function () {
var fieldVal = this;
var fieldInput = $.getFieldControl(fieldVal.key);
var outputVal = fieldVal.value;
if (outputVal) {
var lookupSeparator = ';#';
if (outputVal.indexOf(lookupSeparator) != -1) {
var ind = outputVal.indexOf(lookupSeparator);
var length = lookupSeparator.length;
var startInd = ind + length;
outputVal = outputVal.substring(startInd, outputVal.lenght)
}
fieldInput.val(outputVal);
}
});
}
也许您会注意到插件中有三个辅助函数:getFieldsValues
、getViewFields
和 getCamlQuery
。
getFieldsValues
解析 SPServices 响应,并根据指定的字段映射填充 autcomplete 对象。
//get values for all mapped fields
function getFieldsValues(fieldsMapping, queryResult) {
var result = [];
$.each(fieldsMapping, function () {
var fieldMapping = this;
var val = $(queryResult).attr("ows_" + fieldMapping.sourceField)
result.push({ key: fieldMapping.targetField, value: val, sourceKey: fieldMapping.sourceField});
});
var sourceVal = $(queryResult).attr("ows_" + options.sourceMatchField);
result.push({ value: sourceVal , sourceKey: options.sourceMatchField});
return result;
}
getViewFields
根据字段映射生成 CAML 查询的 ViewFields XML。
//get view fields for all mapped fields
function getViewFields(fieldsMapping) {
var result = "<ViewFields>";
var isSourceFieldAdded = false;
if(fieldsMapping){
$.each(fieldsMapping, function () {
var mapping = this;
var viewField = "<FieldRef Name='" +
mapping.sourceField + "'/>";
result += viewField;
});
isSourceFieldAdded = fieldsMapping.filter(function(){
return this.sourceField == options.sourceMatchField;
}).length > 0;
}
if(!isSourceFieldAdded){
result += "<FieldRef Name='" + options.sourceMatchField + "'/>";
}
result += "</ViewFields>";
return result;
}
getCamlQuery
根据过滤器列的内部名称和输入中的关键字生成 CAML 查询。
//get CAML query for keyword
function getCamlQuery(colname, keyword) {
var where = "<Where><Contains><FieldRef Name='" + colname +
"'></FieldRef><Value Type='Text'>" + keyword +
"</Value></Contains></Where>"
var orderBy = "<OrderBy><FieldRef Name='" + colname + "' Ascending='True' /></OrderBy>"
var query = "<Query>" + where + orderBy + "</Query>";
return query;
}
更新
03.10.2013
- 添加了额外的可选参数:
labelFields
、labelSeparator
、fillConcatenatedLabel
。 - 已实现从源列表中读取查找字段。
- 小的 Bug 修复。