← 全部文档

验证富文本表单字段

必填的富文本字段需要一条应用层规则。HTML 可能不为空,而文档中却没有任何文字。请验证编辑器的当前内容,把它复制到要提交的字段中,并在服务器上再次执行同样的规则。

1. 确定什么算作内容

对于工单描述,您可能要求必须有文字。而对于图片配文工具,一张上传的图片本身就可能是有效的文档。仅检查文字的规则必须是有意拒绝只有图片的文档,而不是意外地丢掉一篇有效的内容。

请把必填内容、最小文本长度和最大载荷大小定义为相互独立的规则。HTML 长度计入了标记,并不等于可读字符数。如果使用 getCharCount() 或 getPlainText(),在把其结果作为业务规则之前,请先确认您所安装的版本如何处理空白、列表和换行。

2. 检测空文本,而不是空标记

// Application policy: this field requires text, not an image-only document.
// Browser-side validation helper. This is NOT an HTML sanitizer.
function hasRequiredText(html) {
  const template = document.createElement("template");
  template.innerHTML = html;
  template.content.querySelectorAll("script, style, template")
    .forEach(node => node.remove());
  return (template.content.textContent || "")
    .replace(/[\s\u00a0\u200b\ufeff]/gu, "").length > 0;
}

这个示例会拒绝空段落、换行、不换行空格和只有图片的内容。它把内容解析到一个与页面分离的模板中,从不把这些内容插入实际页面。它只是检查是否存在文字,而不是安全过滤器或视觉布局测试:被 CSS 隐藏的文字和应用特有的组件需要各自的策略。

对于最小长度,请决定计算的是代码单元、Unicode 码位还是用户感知的字符。JavaScript 的字符串长度对表情符号的计数可能与可见字符不同。请在请求的两端使用同一策略。

3. 复制当前 HTML 并显示有用的错误提示

// Assumes editor1 is ready and these elements exist on your page.
// Leave the editor's hidden textarea without a native required attribute.
const form = document.querySelector("#ticket");
const field = document.querySelector("#body");
const message = document.querySelector("#body-error"); // e.g. <p role="alert">

form.addEventListener("submit", event => {
  const html = editor1.getHTMLCode();
  field.value = html; // Include programmatic edits in the submitted value.
  if (!hasRequiredText(html)) {
    event.preventDefault();
    message.textContent = "Please enter a description.";
    editor1.focus();
    return;
  }
  message.textContent = "";
  // Normal form submission continues to your application's endpoint.
});

编辑器的 textarea 被隐藏之后,浏览器原生的 required 验证就无法可靠地充当编辑器的必填规则。普通表单控件可以继续使用常规验证,但编辑器的规则要针对其当前内容实现。不要给隐藏的后备字段加上原生 required 约束,并指望出现一个可获得焦点的错误提示。

在初始化完成之前,请保持 Save 处于禁用状态。验证失败时,保留草稿,在字段附近显示可见的消息,并把焦点移回编辑器。请使用您的集成方式所支持的无障碍钩子,把消息关联到实际的可编辑区域;只在隐藏的 textarea 上设置属性,并不能为编辑区域提供标签。

这段代码只涵盖同步的文本验证。如果有图片正在上传,提交之前请遵循上传完成与保存的顺序。在 React 中,请按照编辑器状态与保存中的说明,在提交时读取当前内容。

4. 在服务器端净化之后再次验证

客户端可以绕过浏览器检查。请对保存操作进行身份验证和授权,强制执行请求和存储限制,使用一个持续维护、基于解析器的策略净化 HTML,然后再判断被接受的文档是否满足您的内容规则。只包含被拒绝标记的文档,不能变成一条被接受的空记录。

返回针对该字段的错误,并让用户的草稿保持可用。绝不要在错误响应中以未转义的形式渲染被拒绝的 HTML。如需接收和存储内容的 C# 或 PHP 示例,请从您所用语言的演示和富文本存储指南开始。

验收清单

  • 空编辑器、空白段落和不换行空格会被拒绝。
  • 普通文本、带格式的文本以及用户输入的各种语言都能被接受。
  • 只有图片的内容遵循明确的策略。
  • 以编程方式加载的内容会包含在提交中。
  • 验证错误会保留内容,并且可以通过键盘和屏幕阅读器访问。
  • 服务器会拒绝无效的直接请求,而不依赖 JavaScript。

可以试试表单提交演示,阅读为什么必填字段会接受空 HTML,或者查看 textarea 安装。