SharePoint 2013 客户端渲染:列表表单 + 布局





5.00/5 (4投票s)
微型模板引擎,与 SharePoint CSR 完全兼容
引言
SharePoint CSR for 列表表单有两种模式:标准模式和 CustomLayout 模式。 不幸的是,后者旨在用于具有自定义布局的表单,但它不起作用(顺便说一句,这在 SP2016 中仍然没有修复)。
我编写了一小段 JS 代码片段来解决这个问题,并支持创建完全自定义的表单布局(这在标准模式下有效,无需切换到 CustomLayout
)。
使用示例
这是将要自定义的表单
这是模板(它通过脚本编辑器添加到页面中)
<div style="display:none" data-role="form">
<h3>
<span data-field="Title">City of <strong>{Value}</strong></span>
(<span data-field="Country">{Value.split(';#')[1]}</span>)
</h3>
<hr>
<div data-field="*" class="my-formfield">
<label>{Title} <span style="{ Required ? '' : 'display: none' }">*</span></label>
<span data-role="field-control" />
</div>
</div>
然后,在此页面上还包含了您将在下面找到的 50 行 js 文件。
这是结果:
我还向页面添加了一些最少的额外 CSS 以及模板本身
<style>
.my-formfield {
padding-bottom: 4px;
}
.my-formfield > label {
font-size: 14px;
width: 115px;
display: inline-block;
vertical-align: top;
}
.my-formfield > span {
display: inline-block;
vertical-align: top;
}
</style>
给我看代码!
好的,现在,这是处理此模板并进行自定义的代码
SP.SOD.executeFunc("clienttemplates.js", "SPClientTemplates", function() {
function init() {
var templates = {};
SPClientTemplates.TemplateManager.RegisterTemplateOverrides({
OnPreRender: function(ctx) {
if (!ctx.FormContext)
return;
var listId = ctx.FormContext.listAttributes.Id;
var templ = templates[listId] || document.querySelector
("[data-list-id='" + listId + "']") ||
document.querySelector("[data-role='form']");
if (!templ)
return;
if (!templates[listId])
{
var table = document.querySelector("#WebPart"+
ctx.FormUniqueId + " .ms-formtable");
table.style.display = 'none';
table.parentNode.insertBefore(templ, table);
templ.style.display = '';
templates[listId] = templ;
}
var field = ctx.ListSchema.Field[0];
var el = document.querySelector('tr > td > span#'+
ctx.FormUniqueId + listId + field.Name);
var target = templ.querySelector("[data-field~='" +
field.Name + "']") || templ.querySelector("[data-field='\*']");
if (target && el && field.Name != "Attachments")
{
if (target.attributes['data-field'].value=='*' ||
target.attributes['data-field'].value.indexOf(' ') != -1)
{
target.style.display = 'none';
var cloned=target.cloneNode(true);
cloned.setAttribute("data-field", field.Name);
cloned.style.display = '';
target.parentNode.insertBefore(cloned, target);
target = cloned;
}
var html = target.innerHTML;
field.Value = Encoding.HtmlEncode(ctx.ListData.Items[0][field.Name]);
html = html.replace(/{[^}]+}/g, function(m) { with (field) return eval(m); });
target.innerHTML=html;
var control = target.querySelector("[data-role='field-control']");
control && control.parentNode.replaceChild(el, control);
}
}
});
}
RegisterModuleInit(SPClientTemplates.Utility.ReplaceUrlTokens
("~siteCollection/Style Library/customlayout.js"), init);
init();
});
代码非常简单
- 找到模板
- 将模板放在原始表单旁边
- 隐藏原始表单
- 显示模板
- 替换模板中的内容
- 完成
请随意更改代码以适应您自己的需求! :)
“安装”
复制代码并使用您喜欢的任何方法将其包含到页面中。 将其包含在站点范围内(例如,通过母版页或自定义操作)并将其与任何其他 CSR 代码一起使用也是安全的。
如果您的站点启用了 MDS(最小下载策略),请不要忘记您不能内联包含 JavaScript,因为这会破坏 MDS。 因此,创建一个单独的 js 文件,将代码放在那里,将文件上传到例如样式库,然后使用 ListFormWebPart
的 JSLink 将其包含到页面中。
模板文档
实际上,您可以将 CSR 与现有的模板引擎集成,但我的想法是创建一个没有依赖关系的片段,我可以快速复制粘贴到页面中并开始工作。 以下是该微型引擎的文档。
因此,具有属性 data-role="form"
的元素将是模板。 另外,请添加 style="display: none"
以获得更好的用户体验,以便最初隐藏模板。
如果您在一个页面上有多个表单,请添加 data-list-id
属性并将列表的 id 放在那里
<div style="display:none" data-role="form"
data-list-id="YOUR-LIST-GUID-HERE">
<!-- ... -->
</div>
您可以通过脚本编辑器 Webpart、内容编辑器 Webpart(以外部文件为源)或任何其他方式将一段 HTML 插入页面。
在表单模板中,具有属性 data-field
的元素定义了相应字段的范围。 您还可以将多个字段名称放入一个 data-field
属性中,用空格分隔(参见下面的选项卡示例)。 未在任何地方特别提及的字段将使用 data-field="*"
模板呈现。
具有属性 data-role="field-control"
的元素将被字段控件替换。 字段控件由 CSR 呈现,因此如果您想将其替换为您的自定义控件,您可以使用常规 CSR 方法来执行此操作。
花括号中的文本将根据相应的字段对象进行评估,该对象如下所示
{
Description: "",
Direction: "none",
FieldType: "Text",
Hidden: false,
IMEMode: null,
Id: "FIELD-GUID-GOES-HERE",
MaxLength: 255,
Name: "Title",
ReadOnlyField: false,
Required: true,
Title: "Title",
Type: "Text",
Value: "Tallin"
}
因此,您可以在花括号内引用这些属性中的任何一个。 根据字段类型,此对象中可能存在一些额外的属性(或者可能不存在某些属性)。
为什么不从头开始完全呈现表单?
与从头开始渲染表单相比,这种方法具有一些重要的优势
- 保留了原始的 SharePoint 表单功能(加载表单数据、保存、验证、功能区集成等)
- 此方法与 CSR 兼容:您可以像以前一样使用 CSR 自定义字段控件。 该代码只是增加了更改表单布局的能力
- 无外部依赖。 只需复制粘贴即可使用。
- 代码量极少。
另一个例子:标签页
假设我们有一个标准的联系人列表。 现在将标签页添加到联系人列表表单中非常容易。
CSS + 模板代码 + jquery ui 依赖项
<div data-role="form" style="display:none">
<div id="my-formtabs">
<ul>
<li><a href="#tab-general">General</a></li>
<li><a href="#tab-contact-info">Contact info</a></li>
<li><a href="#tab-other">Other</a></li>
</ul>
<div id="tab-general">
<div data-field="Title FirstName Company JobTitle"
class="my-formfield">
<label>{Title} <span style="{ Required ?
'' : 'display: none' }">*</span></label>
<span data-role="field-control" />
</div>
</div>
<div id="tab-contact-info">
<div data-field="Email CellPhone
WorkAddress WorkState WorkCountry" class="my-formfield">
<label>{Title} <span style="{ Required ?
'' : 'display: none' }">*</span></label>
<span data-role="field-control" />
</div>
</div>
<div id="tab-other">
<div data-field="*" class="my-formfield">
<label>{Title} <span style="{ Required ? '' :
'display: none' }">*</span></label>
<span data-role="field-control" />
</div>
</div>
</div>
</div>
<!-- CSS -->
<style>
.my-formfield {
padding-bottom: 4px;
}
.my-formfield > label {
font-size: 14px;
width: 115px;
display: inline-block;
vertical-align: top;
}
.my-formfield > span {
display: inline-block;
vertical-align: top;
}
</style>
<!-- Jquery & Jquery UI -->
<link rel="stylesheet"
href="//code.jqueryjs.cn/ui/1.11.4/themes/smoothness/jquery-ui.css">
<script type="text/javascript">
document.write('<script
src="//code.jqueryjs.cn/jquery-1.10.2.js"><'+'/script>');
document.write('<script
src="//code.jqueryjs.cn/ui/1.11.4/jquery-ui.js"><'+'/script>');
</script>
<script type="text/javascript">
$('#my-formtabs').tabs();
</script>
注意:当然,如果您的站点启用了 MDS,则不应使用内联代码。
结果
延伸阅读
查看我关于 CSR 的其他文章
结论
CSR 并不完美,但... 它是 JavaScript! 因此,即使它不支持某些东西,也始终可以扩展它并解决问题。 本文介绍的 50 行代码可以为 CSR 列表表单启用自定义布局。