给 SpreadJS 单元格装上自动完成

客服工单系统里有一张设备登记表,其中一列要填产品型号。型号库里有几百个条目,名称长得还像:PRO-2000、PRO-2000S、PRO2-K。从几百项的下拉里翻找和凭记忆手打,体验都糟糕。用户想要的是第三种交互------打两个字母,候选浮出来,点一下填好。这就是常见的自动完成(autocomplete):SpreadJS 单元格默认没有这个能力,但留了把它接进去的口子。

思路:把现成的编辑器挂进单元格

SpreadJS 提供了基类 GC.Spread.Sheets.CellTypes.Base,自定义单元格类型继承它之后可以接管单元格的整个编辑生命周期:createEditorElement 创建编辑器 DOM、activateEditor 激活时绑定行为、deactivateEditor 退出时清理、getEditorValue 在提交前决定什么值允许写入。

做法很直接:让 createEditorElement 返回一个 input 元素,在 activateEditor 里对它初始化 jQuery UI 的 autocomplete 组件,把候选词数组交给 source。再补一个细节------获得焦点时就调一次 search,不输字符也能看到候选。退出编辑时调用 autocomplete('destroy') 清理实例,避免事件残留。

javascript 复制代码
AutocompleteCellType.prototype = new GC.Spread.Sheets.CellTypes.Base();
AutocompleteCellType.prototype.createEditorElement = function () {
    return document.createElement("input");
};
AutocompleteCellType.prototype.activateEditor =
        function (editorContext, cellStyle, cellRect, context) {
    $(editorContext).autocomplete({
        minLength: 0,
        source: this.availableTags
    }).focus(function () {
        $(this).autocomplete('search', $(this).val());
    });
    // 标记为 SpreadJS 编辑器元素,点击候选项时不丢失焦点
    $(editorContext).autocomplete("widget")
        .attr("gcUIElement", "gcEditingInput");
    return $(editorContext);
};

gcUIElement 值得单独说一句:它是 SpreadJS 识别自己 UI 元素的标记,把下拉候选面板也标上它,鼠标点到候选上时表格才不会误判为"点了外面"而结束编辑。

只靠提示还不够,要把口子也收住

自动完成只是引导,挡不住越界输入。粘贴进来一个不在候选里的值怎么办?这份实现给了三道补充闸门。

第一道在提交时:重写 getEditorValue,检查输入是否在 source 里,不在且配置为不可自定义(示例中的 isEditable 开关)就返回 null,这次编辑等于没发生。第二道在粘贴后:监听 Events.ClipboardPasted 事件,遍历粘贴区域,凡是自动完成列的单元格,值不在候选集里就清空。第三道在键盘上:重写 isReservedKey,编辑状态下把上下方向键声明为单元格类型自己处理,上下键用来在候选列表里移动,不会被表格抢去切换选中单元格。

另外,整列应用用的是 sheet.getRange(-1, 1, -1, 1).cellType(...);再配一个 cellButtons 下拉按钮,回调里用 startEdit(false) / endEdit(true) 切换编辑状态,点一下就能展开全部候选。

可以扩展到哪些场景

凡是"选项多到下拉翻不动、但取值范围有限"的字段都适用:物料编码、客户名称、会计科目。配合 minLength 还能做检索优化------字典量大时设为 2 或 3,敲够几个字符才发起匹配,避免一次渲染上千个候选。数据源换成接口返回的异步数组,就是一张联网联想录入表。

给开发者的关键词

GC.Spread.Sheets.CellTypes.Base、createEditorElement、activateEditor、deactivateEditor、getEditorValue、isReservedKey、cellButtons、startEdit、endEdit、Events.ClipboardPasted、autocomplete、minLength。

小结

这个方案的本质,是把 Web 世界成熟的输入组件嫁接进电子表格的编辑体系:Base 类管生命周期,autocomplete 管联想,三个小钩子守住数据边界。代码量不大,却同时照顾到录入效率和数据质量两端。

相关推荐
恋猫de小郭1 小时前
Flutter 多窗口重要优化合并,多窗口性能和实用性大幅提升
android·前端·flutter
StudyAndLife1 小时前
开源一个 API 开放平台门户前端:本地 npm run dev 就能逛接口文档
前端
广州华水科技1 小时前
GNSS变形监测一体机在大坝安全监测中的应用与优势分析
前端
hunteritself1 小时前
夯爆了!Qoder 狂肝 2 小时,293 个测试全绿,Credits 一分没扣
前端·人工智能·chrome·深度学习·机器学习
Hilaku2 小时前
为什么前端应该主动去学数据库?
前端·javascript·程序员
涛涛ing2 小时前
2026年,你终于可以在 `<textarea>` 里定位任意字符了
前端
三8442 小时前
TLS + Web API 安全 · 05 · JWT 与 OAuth2 攻防
前端·安全
zhongwei2283 小时前
vba将一个文件夹的内容复制到另外一个文件夹的函数,若存在则是否覆盖的参数。复制前检查源文件夹是否存在。若目标文件夹不存在,则新建
前端·vba
怕浪猫4 小时前
分享一个做视频的skill,这条白板视频,每一笔都是代码画的
前端·javascript·面试