什么?AntV/S2 还能做成 Excel 形态?

简介: 什么?AntV/S2 还能做成 Excel 形态?
🙋🏻‍♀️ 编者按:产品突然指过来一个需求,需要在 S2 大数据的表格里面,添加可编辑功能。这可咋整呀?S2 的主打的是数据展示,而不是数据编辑,看来只能自己试试黑魔法了😏。本文中,AntV 团队的亚德将为大家演示,如何把 S2 数据展示表格变成编辑表格,欢迎享用~

怎么快速搭建一个 S2 表格?

让我们看下 S2 的官网 s2.antv.vision/,然后快速搭建一个明细表

import React, { useState, useRef } from 'react';
import ReactDOM from 'react-dom';
import { SheetComponent } from '@antv/s2-react';
import '@antv/s2-react/dist/style.min.css';
import 'antd/es/checkbox/style/index.css';
import { S2DataConfig, S2Options, SpreadSheet } from '@antv/s2';
const initOptions = {
  width: 600,
  height: 400,
  showSeriesNumber: true,
  tooltip: { showTooltip: false },
  interaction: { enableCopy: true, },
  showDefaultHeaderActionIcon: false,
}
const initData = {
  fields: { columns: ['province', 'city', 'type', 'price'], },
  sortParams: [],
}
const App = ({ data }) => {
  const S2Ref = useRef<SpreadSheet>(null);
  const [options, setOptions] = useState<S2Options>(initOptions);
  const [dataCfg, setDataCfg] = useState<S2DataConfig>({ ...initData, data });
  return (
    <div>
      <SheetComponent
        ref={S2Ref}
        dataCfg={dataCfg}
        options={options}
        sheetType="table"
        />
    </div>
  );
};
fetch('../data/basic-table-mode.json')
  .then((res) => res.json())
  .then((res) => {
  ReactDOM.render(<App data={res} />, document.getElementById('container'));
});

然后让我们看看这个表格长什么样?

那怎么把数据展示表格变成编辑表格呢?

1. 先来一个受控的编辑元素

<input value={value} onChange={e => setValue(e.target.value)} />

那要如何把这个编辑元素和表格内的展示元素绑定在一起呢?

诶,S2 不是有个事件机制么?我们是不是可以把 click 事件获取到,然后将我们的编辑元素盖到展示元素的上面?找了下 API,果然有一个可以用来监听数据格的点击事件(S2Event.DATA_CELL_CLICK)。

2. 注册一个 DATA_CELL_CLICK 事件,触发后保存当前点击 Cell 的信息

S2Ref.current.on(S2Event.DATA_CELL_CLICK, (e) => {
  // 保存当前cell
  setCell(e.target.cfg.parent)
})

为什么需要保存 Cell 的信息呢?因为我们接下来要使用这个信息去排版我们的编辑元素。那怎么获取通过 cell 获取到当前 cell 的坐标以及宽高信息呢?cell 的这些信息都挂载在 cellMeta 上面,使用 cell.getMeta() 即可快速获取到这些信息,然后我们将这些信息拼装一下,变成我们需要的 style 数据。同时还得把原始数据赋值给这个编辑元素,使得用户无缝切换编辑和展示模式。

3. 通过当前 Cell 信息将受控编辑元素覆盖到当前 Cell 上方,同时赋初始值

useEffect(() => {
    const spreadsheet = S2Ref.current
    if (spreadsheet && cell) {
      const cellMeta = pick(cell.getMeta(), ['x', 'y', 'width', 'height', 'fieldValue']);
      const colCellHeight = (spreadsheet.getColumnNodes()[0] || { height: 0 }).height
      cellMeta.x -= scroll.scrollX || 0;
      cellMeta.y -= (scroll.scrollY || 0) - colCellHeight;
      setPosition({
        left: cellMeta.x,
        top: cellMeta.y,
        width: cellMeta.width,
        height: cellMeta.height,
      })
      setShow(true)
      setValue(cellMeta.fieldValue)
    }
  }, [cell])

另外,还发现一个不是很舒服的体验,点击之后没有自动focus到编辑元素上,这个问题怎么优化呢?

也很简单,只要在 show 的时候自动 focus 就好。

// show的时候自动focus
  useEffect(() => {
    if (inputRef.current) {
      inputRef.current.focus({ preventScroll: true })
    }
  }, [show])

已经有了一个覆盖在 S2 上方的编辑元素,那么接下来我们就要考虑如何将修改后的值同步到 S2 内部。再来看看现在我们的表格长什么样子?

4. 使用回车键触发保存功能

4.1 save 函数

// 改变S2实际渲染内容
  const onSave = (inputVal: string) => {
    const spreadsheet = S2Ref.current
    if (spreadsheet && cell) {
      const { rowIndex, valueField } = cell.getMeta();
      spreadsheet.dataSet.originData[rowIndex][valueField] = inputVal;
      spreadsheet.render(true);
      setShow(false)
    }
  }

通过修改 originData 然后再调用 render 函数即可做到更新 S2 数据的功能,是不是很简单?渲染完成之后再把我们用来控制渲染元素的 show 置为 false 来隐藏编辑元素。

4.2 添加 keydown 事件,回车的时候触发保存功能

// 绑定回车键 回车的时候触发保存
  useEffect(() => {
    const onKeyDown = (e) => {
      if (e.keyCode === 13) {
        e.preventDefault();
        onSave(value);
      }
    };
    if (inputRef.current) {
      inputRef.current.addEventListener('keydown', onKeyDown)
    }
    return () => {
      inputRef.current?.removeEventListener('keydown', onKeyDown)
    }
  }, [value])

记得解绑事件哦,防止内存泄漏。来看看效果

但是用户不一定非得使用回车保存内容,和 Excel 类似,编辑元素失去焦点的时候,应该也是需要触发保存的,这个功能我们要怎么去实现呢?

5. 切换 Cell 之前,先保存当前编辑的值

// 绑定 S2Event.DATA_CELL_CLICK 事件,触发时先将上一个cell的值保存,然后设置当前cell
  useEffect(() => {
    const spreadsheet = S2Ref.current
    const handleClick = (e) => {
      onSave(value)
      setCell(e.target.cfg.parent)
    }
    if (spreadsheet) {
      spreadsheet.on(S2Event.DATA_CELL_CLICK, handleClick)
    }
    return () => {
      spreadsheet?.off(S2Event.DATA_CELL_CLICK, handleClick)
    }
  }, [value])

让我们在看看效果

正当我沾沾自喜要把代码 push 上去的时候,不小心碰到了鼠标滚轮,然后他变成这样了。😱😱😱
这可咋办,明天就要上线了!这个编辑元素居然不会跟着滚动!又翻阅了 S2 的事件列表,找到了一个事件S2Eevnt.LAYOUT_CELL_SCROLL,可以用来监听滚动事件。完美!😼😼😼

6. 监听滚动事件,使得编辑元素动态滚动

useEffect(() => {
    const spreadsheet = S2Ref.current
    const handleScroll = (e) => {
      if (spreadsheet) {
        const newScroll = spreadsheet.facet.getScrollOffset()
        if (!isEqual(newScroll, scroll)) {
          setScroll(spreadsheet.facet.getScrollOffset())
        }
      }
    }
    if (spreadsheet) {
      spreadsheet.on(S2Event.LAYOUT_CELL_SCROLL, handleScroll)
    }
    return () => {
      spreadsheet?.off(S2Event.LAYOUT_CELL_SCROLL, handleScroll)
    }
  }, [])

同时监听 scroll 的改动

// 监听滚动
  useEffect(() => {
    const spreadsheet = S2Ref.current
    if (spreadsheet && cell) {
      const cellMeta = pick(cell.getMeta(), ['x', 'y', 'width', 'height', 'fieldValue']);
      cellMeta.x -= scroll.scrollX || 0;
      cellMeta.y -=
        (scroll.scrollY || 0) -
        (spreadsheet.getColumnNodes()[0] || { height: 0 }).height;
      setPosition({
        left: cellMeta.x,
        top: cellMeta.y,
        width: cellMeta.width,
        height: cellMeta.height,
      })
    }
  }, [scroll])

我们再来看看效果

好了,一个简单的可编辑表格就在 S2 灵活的底层基础上实现了,是不是忍不住自己也想来尝试来一把?
在线预览地址 https://s2.antv.vision/zh/examples/case/data-preview#excel

欢迎 star 以及 fork!让我们一起 DIY 起来~

https://github.com/antvis/S2 🌟🌟🌟

相关文章
|
5月前
|
数据采集 SQL 数据可视化
大数据可视化技巧:借助PowerBI提升数据故事讲述力
【4月更文挑战第8天】Power BI助力大数据可视化,支持多种数据源连接,如SQL Server、Excel,提供数据清洗与转换功能。通过选择合适图表类型、运用颜色和大小强化表达,创建交互式仪表板。讲述数据故事时,注重故事主线设计,利用叙事技巧引导观众,并添加文本说明。分享已完成报告,提升数据驱动决策能力。动手实践,体验Power BI的强大与易用。
157 0
|
2月前
|
数据可视化 前端开发 JavaScript
本来不想分享的,但这套可视化大屏确实不错
本来不想分享的,但这套可视化大屏确实不错
|
5月前
|
数据可视化 Java BI
商业开源MES+源码+送可拖拽式数据大屏
这是一个商业开源的JAVA MES系统,包含源码和本地部署教程。基于Springboot、Vue3和MySQL8,适用于开发学习。功能包括车间数据建模、生产物料控制、计划管理、过程控制、质量管理、库存管理、看板管理、报表分析和基础管理。需JDK11、Tomcat及Maven环境,源码付费获取。
106 0
|
JavaScript 前端开发 数据库
Unity3d(webGL)构建数字孪生小案例(包含完整的数据交互体系)附赠完整代码
Unity3d(webGL)构建数字孪生小案例(包含完整的数据交互体系)附赠完整代码,请关注公众号:拼搏的小浣熊,获取简化版的代码!
|
SQL 移动开发 编解码
如何使用 AntV S2 打造大数据表格组件?
如何使用 AntV S2 打造大数据表格组件?
1081 0
|
vr&ar 图形学 Windows
CATIA等设计类软件实时渲染流化解决方案
**实时渲染技术可以实现在VR/AR眼镜中查看CATIA模型,其实不仅仅是VR和AR眼镜,还可以是手机、平板、电脑中直接打开网页就可以查看和浏览CATIA等3D模型。而VR/AR眼镜中通过实时渲染技术不仅仅可以查看CATIA模型,其他的比如BIM/Unreal/unity等模型也都是OK的。**那具体是怎么实现的呢?使用起来麻烦吗?能不能支持多人同时使用呢?关于这些对于实时渲染比较相关的问题,这里点量云小芹做统一解释说明。
204 0
CATIA等设计类软件实时渲染流化解决方案
|
存储 数据采集 数据可视化
教您通过NBI大数据可视化工具零编码轻松实现桑基图的制作
人人都是数据分析师的时代,我们如何才能真正让普通用户拥有数据分析的能力,我们都知道要想掌握大数据分析,首先在技术层面就得有一定的技术深度和广度,数据分析大致分为数据采集,数据存储,数据建模计算,数据可视化分析四个阶段,要想掌握这些能力,那大家可能想到的是需要一个有实力的团队才能做到吧,那今天就给大家介绍一款大数据可视化分析工具(更多资料了解:http://nbi.easydatavis.com:8033),通过零编码,简单快速实现数据可视化分析 NBI一站式数据可视化分析平台(更多资料了解:http://nbi.easydatavis.com:8033) NBI一站式大数据分析平台作为新一
教您通过NBI大数据可视化工具零编码轻松实现桑基图的制作
|
数据可视化 安全 数据挖掘
NBI可视化平台内置多种风格多套模板,做数据可视化不费劲
NBI可视化平台版本已经更新到4.9.1啦,在NBI可视化平台4.9.1版本中内置了多种风格、多套模板可以供用户选择使用,并且在可视化视觉上面做了增强
NBI可视化平台内置多种风格多套模板,做数据可视化不费劲
|
搜索推荐 easyexcel Java
阿里开源的这个库,让 Excel 导出不再复杂(既要能写,还要写的好看)
前文 聊了 EasyExcel 的内容导出,本文主要说一下导出文件的格式化,格式化包括工作表/单元格样式和内容格式化。毕竟,有时候还是要看脸。
1102 0
阿里开源的这个库,让 Excel 导出不再复杂(既要能写,还要写的好看)
|
弹性计算 Kubernetes 网络协议
图表即代码:使用 Diagrams 制作云系统架构原型图
## 一、前言 昨天发现了一款非常不错的云系统架构原型图制作库 [Diagrams](https://github.com/mingrammer/diagrams "Diagrams"),通过它,我们便可以使用代码的方式绘制诸如阿里云、AWS、Azure、K8S 等系统架构原型图。 相比于在 UI 上对各种图标进行拖拽和调整,这种方式更符合我们程序员的使用习惯。 本文不仅要介绍下
2112 1