65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.93/5 (6投票s)

2013年8月16日

CPOL

5分钟阅读

viewsIcon

69529

downloadIcon

7

本文介绍如何使用 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 插件 

您可以直接使用此插件,无需查看代码。首先,我将描述如何使用它,然后如果您仍然感兴趣,可以查看插件的实现。

必备组件

如果您还没有 jQueryjQuery UISPServices,可以从官方网站下载最新版本。为方便教程,我假设下载的文件和文件夹名称如下:

  • 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.jsjquery.SPServices.min.jsjquery-ui-1.10.3.custom.min.jsjquery.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() 函数中,以确保代码在页面加载后执行。

让我们更详细地看一下这个代码示例。代码分为两部分:

  1. 获取自动完成字段的控件
  2. 为字段控件调用自动完成插件

第一步,您需要为 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'
});

插件的内部实现

让我们看完整的插件源代码。您可以 在此处 下载。

代码中有三个主要部分:

  1. 获取文本字段输入。 
  2. 应用 jQueryUIi 自动完成插件和 SPServices 以获取建议。
  3. 实现辅助函数。

为了获取字段输入,我使用了 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 自动完成插件,并实现了 sourceselect 插件函数。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);
        }
    });
}

也许您会注意到插件中有三个辅助函数:getFieldsValuesgetViewFieldsgetCamlQuery

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

  • 添加了额外的可选参数:labelFieldslabelSeparatorfillConcatenatedLabel
  • 已实现从源列表中读取查找字段。 
  • 小的 Bug 修复。
© . All rights reserved.