如何自定义表格字段?

目录

表单字段注册vue组件实现机制

核心代码

public initialize(props) {
  super.initialize(props);
  this.setComponent(VueComponent);
  return this;
}

表格字段注册vue组件实现机制

核心代码

@Widget.Method()
public renderDefaultSlot(context: RowContext) {
  const value = this.compute(context);
  return [createVNode(CustomTableString, { value })];
}

因为表格有行跟列,每一列都是一个单独的字段(对应的是TS文件),但是每列里面的单元格承载的是Vue组件,所以通过这种方式可以实现表格每个字段对应的TS文件是同一份,而单元格的组件入口是通过renderDefaultSlot函数动态渲染的vue组件,只需要通过createVNode创建对应的vue组件,然后将props传递进去就行

上下文接口

interface RowContext<T = unknown> {
  /**
   * 当前唯一键, 默认使用__draftId, 若不存在时,使用第三方组件内置唯一键(如VxeTable使用{@link VXE_TABLE_X_ID})
   */
  key: string;
  /**
   * 当前行数据
   */
  data: Record<string, unknown>;
  /**
   * 当前行索引
   */
  index: number;
  /**
   * 第三方组件原始上下文
   */
  origin: T;
}

机制对比分析

表单字段 vs 表格字段渲染机制对比表

对比维度 表单字段实现方案 表格字段实现方案
绑定时机 initialize 阶段静态绑定 renderDefaultSlot 阶段动态创建
组件声明方式 this.setComponent(Component) createVNode(Component, props)
上下文传递 通过类成员变量访问 显式接收 RowContext 参数
渲染控制粒度 字段级(表单控件) 单元格级

表格字段完整案例

import { SPI, ViewType, BaseFieldWidget, Widget, TableNumberWidget, ModelFieldType, RowContext } from '@kunlun/dependencies';
import CustomTableString from './CustomTableString.vue';
import { createVNode } from 'vue';

@SPI.ClassFactory(
  BaseFieldWidget.Token({
    ttype: ModelFieldType.String,
    viewType: [ViewType.Table],
    widget: 'CustomTableStringWidget'
  })
)
export class CustomTableStringWidget extends BaseTableFieldWidget {
  @Widget.Method()
  public renderDefaultSlot(context:RowContext) {
    const value = this.compute(context); // 当前字段的值
    const rowData = context.data // 当前行的数据
    const dataSource = this.dataSource // 表格数据

    if (value) {
      // 自定义组件入口在此处
      return [createVNode(CustomTableString, { value })];
    }
    return [];
  }
}
<template>
  <div>当前值: {{value}}</div>
</template>

<script  lang="ts">
import { defineComponent } from 'vue'

export default defineComponent({
  props: ['value']
})
</script>

Oinone社区 作者:汤乾华原创文章,如若转载,请注明出处:https://doc.oinone.top/frontend/4246.html

访问Oinone官网:https://www.oinone.top获取数式Oinone低代码应用平台体验

(0)
汤乾华的头像汤乾华数式员工
上一篇 2023年11月3日 pm3:36
下一篇 2023年11月6日 pm2:33

相关推荐

  • 表格主题配置(v4)

    TableThemeConfig /** * 表格主题配置 */ export interface TableThemeConfig { border: boolean | string; stripe: boolean; isCurrent: boolean; isHover: boolean; /** * 表格列主题配置 */ column: Partial<TableColumnThemeConfig>; } /** * 表格列主题配置 */ export interface TableColumnThemeConfig { /** * <h3>最小宽度</h3> * <ul> * <li>boolean: enabled column width auto compute</li> * <li>number: using css width (default: px)</li> * <li>string: using css width</li> * <li> * object: auto compute width for label by default function * <ul> * <li>min: min min width (default: 120)</li> * <li>max: max min width (default: 432)</li> * <li>chineseWidth: chinese width (default: 14 -> fontSize: 14px)</li> * <li>otherWidth: non chinese width (default: 9 -> fontSize: 14px)</li> * <li>sortableFixWidth: sortable handle width (default: 40)</li> * <li>nonSortableFixWidth: non sortable fix width (default: 22)</li> * </ul> * </li> * <li>function: auto compute width for label by function</li> * </ul> */ minWidth: boolean | number | string | Partial<TableColumnMinWidthComputeConfig> | TableColumnMinWidthComputeFunction; /** * 操作列 */ operation: { /** * 宽度 (default: 165) */ width?: number | string; /** * 最小宽度 (default: 120) */ minWidth?: number | string; }; } export interface TableColumnMinWidthComputeConfig { min: number;…

    2023年11月6日
    1.2K00
  • 左树右表页面,点击表格的新建按钮,获取选中的树节点

    左树右表页面,点击表格的新建按钮,获取选中的树节点 通过自定义action的方式来实现 新建一个action文件TreeActionWidget.ts import { ActionType, ActionWidget, SPI, ViewActionTarget, RouterViewActionWidget } from '@kunlun/dependencies'; import { OioNotification } from '@kunlun/vue-ui-antd'; @SPI.ClassFactory( ActionWidget.Token({ actionType: [ActionType.View], target: [ViewActionTarget.Router], name: 'uiView0000000000079503' // action对应的name }) ) export class TreeActionWidget extends RouterViewActionWidget { protected async clickAction() { const context = this.rootRuntimeContext.view.context || {}; const activeTreeContext = context.activeTreeContext || null; if (!activeTreeContext) { // 没有选中左侧树 OioNotification.error('', '请选择左侧节点!'); } else { // 选中的时候 (this.action as any).context = activeTreeContext; // 执行原先的action逻辑 super.clickAction(); } } }

    2023年11月1日
    1.1K00
  • 【界面设计器】自定义字段组件基础

    阅读之前 本文档属于高阶实战文档,已假定你了解了所有必读文档中的全部内容,并了解过界面设计器的一些基本操作。 如果在阅读过程中出现的部分概念无法理解,请自行学习相关内容。【前端】文章目录 概述 平台提供的字段组件(以下简称组件)是通过SPI机制进行查找并最终渲染在页面中。虽然平台内置了众多组件,但无法避免的是,对于业务场景复杂多变的实际情况下,我们无法完全提供所有组件。 面对这样的困境,我们提供了外部注册组件的方式。在之前文章中,我们了解到组件注册后需要应用到页面中,需要配合DSL才能实现。其实,在平台中还提供了一种SAAS化的组件注册方式,配合界面设计器的设计能力,可以将组件在设计器页面中引入,从而更近一步的满足不同的业务场景。 通过界面设计器可以创建自定义组件,并为组件添加对应的元件。 界面设计器可以为元件设计其在指定视图下的属性面板,在页面设计时,可以使用该属性面板为元件设置相关属性。 在界面设计器的设计页面中拖入的组件,将通过SPI机制获取到一个唯一的元件,并渲染在页面中,提供给业务使用。 界面设计器-组件管理 名词解释 页面设计:使用界面设计器设计页面的页面。 属性面板设计:使用界面设计器设计属性面板的页面。 设计页面:页面设计和属性面板设计的统称。 组件库:展示在设计页面左侧的全部可拖拽组件。 组件:在组件库中可拖拽的最小单元。 元件:一个组件中的具体实现,是组件的最小单元。 属性面板:展示在设计页面右侧的元件属性。 页面设计 属性面板设计 组件管理入口 进入界面设计器后,可通过上方标签页切换至【组件】管理页面。 创建第一个组件 点击【添加组件】,在弹窗中输入组件名称【文本输入框】后,点击【确定】。 创建第一个元件 点击【组件卡片】或点击【管理元件】按钮进入【元件】管理页面。 点击【添加元件】,可以看到如下【创建元件】弹窗。 表单字段解释 元件名称:显示名称,仅在管理页面做展示使用。 API名称:SPI中的widget属性。 支持字段业务类型:SPI中的ttype属性。 支持多值:SPI中的multi属性。 支持视图类型:SPI中的viewType属性。 元件描述:元件功能描述内容,仅在管理页面做展示使用。 填入以下内容,并点击【确定】。 设计元件属性面板 点击【元件卡片】或点击【设计元件属性】按钮进入【属性面板设计】页面。 从【模型】中搜索【标题】,将【标题】和【隐藏标题】拖放至设计区域。如果想实现的相对美观,可以额外添加【分组】组件拖放至设计区域,并修改标题为【基础】,如下图所示。 点击【发布】按钮进行页面的发布。 至此,我们设计了第一个元件属性面板,接下来,我们需要在页面设计中使用这个组件。 在页面中使用【文本输入框】 由于我们之前选择的支持的视图类型是【表单】,因此我们在【表单】页面进行接下来的操作,此处略去创建视图的过程。 从【模型】中将【名称】拖放至设计区域。并通过点击【切换】按钮切换至我们的组件【文本输入框】,并且将标题改为【这是文本输入框组件】查看其展示效果。 属性变化 在组件切换后,属性面板发生了变化,原有属性会根据当前属性面板中现有字段进行【裁剪】,相同属性名称(字段)的值会被保留,其他属性值会被丢弃。 由于我们并没有在当前属性面板添加【宽度】属性,因此原有属性的宽度被丢弃,组件会自动变成默认【宽度】,默认宽度为1。 组件变化 由于我们并没有在【低无一体】中上传对应元件的代码实现,因此展示了默认的【单行文本】组件,目前组件的展示效果不会发生变化。 组件可切换规则 只有【组件】中包含与【当前选中字段】匹配的【元件】,才会将对应【组件】的名称展示在【可切换列表】中。 【当前选中字段】中包含了如下三个属性,这三个属性和【创建元件】时设置的属性一一对应。 (右侧属性面板切换至字段后,可查看当前选中字段的相关元数据信息。) 所在视图类型:根据字段在视图中的位置进行推断,当前所在位置为【表单】。当【支持视图类型】包含【表单】时条件成立。 字段业务类型:文本。当【支持字段业务类型】包含【文本】时条件成立。 是否多值:否。当【支持多值】相同时条件成立。 使用低无一体为组件上传代码实现 进入【组件】管理页面,点击【低无一体】,打开【低无一体】弹窗。 按照步骤,在【生成SDK】后,可以【下载模板工程】。在本地进行npm相关操作后,会在packages/kunlun-plugin目录下生成dist目录。在dist目录中,会有对应的kunlun-sdk.umd.js文件,使用【上传JS文件】进行上传。如果工程中包含了css,使用【上传CSS文件】进行上传。上传完成后点击【确定】进行保存。 PS:在模板工程中,我们提供了最简化的Hello World示例,即使不添加任何代码也可以看到组件的具体效果,为了方便演示,我们暂时不介绍代码实现的相关内容,仅需直接上传对应js文件,看到效果即可。如果遇到相关问题,请点击查看【前端】低无一体部署常见问题。 结语 至此,我们已经完整体验了从【创建组件】到【属性面板设计】再到【使用组件】以及【实现组件】的全部流程。 通过这一流程我们不难发现,【自定义组件】并非仅仅用于【页面设计】,在【属性面板设计】时,我们同样可以使用【自定义组件】来设计【自定义组件】的属性面板。这样便形成了一个完整的设计闭环,使得开发者可以更大程度的发挥自身创造力,开发出符合业务需求的【自定义组件】。

    2023年11月1日
    2.3K00
  • 前端低无一体使用教程

    介绍 客户在使用oinone平台的时候,有一些个性化的前端展示或交互需求,oinone作为开发平台,不可能提前预置好一个跟客户需求一模一样的组件,这个时候我们提供了一个“低无一体”模块,可以反向生成API代码,生成对应的扩展工程和API依赖包,再由专业前端研发人员基于扩展工程(kunlun-sdk),利用API包进行开发并上传至平台,这样就可以在界面设计器的组件里切换为我们通过低无一体自定义的新组件。 低无一体的具体体现 “低”— 指低代码,在sdk扩展工程内编写的组件代码 “无”— 指无代码,在页面设计器的组件功能处新建的组件定义 低无一体的组件跟直接在自有工程内写组件的区别? 低无一体的组件复用性更高,可以在本工程其他页面和其他业务工程中再次使用。 组件、元件介绍 元件 — 指定视图类型(viewType) + 指定业务类型(ttype)字段的个性化交互展示。组件 — 同一类个性化交互展示的元件的集合。组件是一个大一点的概念,比如常用的 Input 组件,他的元件在表单视图有字符串输入元件、密码输入元件,在详情和表格展示的时候就是只读的,页面最终使用的其实是元件。通过组件+ttype+视图类型+是否多值+组件名可以找到符合条件的元件,组件下有多个元件会根据最优匹配规则找到最合适的具体元件。 如何使用低无一体 界面设计器组件管理页面添加组件 进入组件的元件管理页面 点击“添加元件” 设计元件的属性 这里以是否“显示清除按钮”作为自定义属性从左侧拖入到中间设计区域,然后发布 点击“返回组件” 鼠标悬浮到卡片的更多按钮的图标,弹出下拉弹出“低无一体”的按钮 在弹窗内点击“生成SDK”的按钮 生成完成后,点击“下载模板工程” 解压模板工程kunlun-sdk.zip 解压后先查看README.MD,了解一下工程运行要点,可以先运行 npm i 安装依赖 再看kunlun-plugin目录下已经有生成好的组件对应的ts和vue文件 下面在vue文件内增加自定义代码,可以运行 npm run dev 在开发模式下调试看效果 <template> <div class="my-form-string-input"> <oio-input :value="realValue" @update:value="change" > <template #prepend>MyPrepend</template> </oio-input> </div> </template> <script lang="ts"> import { defineComponent, ref } from 'vue'; import { OioInput } from '@kunlun/vue-ui-antd'; export default defineComponent({ name: 'customField1', components: { OioInput }, props: { value: { type: String }, change: { type: Function }, }, setup(props) { const realValue = ref<string | null | undefined>(props.value); return { realValue }; } }); </script> <style lang="scss"> .my-form-string-input { border: 1px solid red; } </style> 确定改好代码后运行 npm run build,生成上传所需的js和css文件 可以看到 kunlun-plugin目录下多出了dist目录,我们需要的是 kunlun-plugin.umd.js 和 kunlun-plugin.css 这2个文件 再次回到组件的“低无一体”管理弹窗页面,上传上面生成的js和css文件,并点击“确定”保存,到这里我们的组件就新增完成了。 下面我们再到页面设计器的页面中使用上面设计的组件(这里的表单页面是提前准备好的,这里就不介绍如何新建表单页面了) 将左侧组件库拉直最底部,可以看到刚刚新建的组件,将其拖至中间设计区域,我们可以看到自定义组件的展示结果跟刚刚的代码是对应上的(ps: 如果样式未生效,请刷新页面查看,因为刚刚上传的js和css文件在页面初始加载的时候才会导入进来,刚刚上传的动作未导入新上传的代码文件),再次点击设计区域中的自定义组件,可以看到右侧属性设置面板也出现了元件设计时拖入的属性。 最后再去运行时的页面查看效果,与代码逻辑一致! 注意事项 为什么我上传了组件后页面未生效? 检查前端启动工程的低无一体是否配置正确

    2023年11月6日
    3.3K00
  • 【界面设计器】自定义字段组件实战——千分位输入框

    阅读之前 此文章为实战教程,已假定你熟悉了【界面设计器】较为完整的【自定义组件】相关内容。 如果在阅读过程中出现的部分概念无法理解,请自行学习相关内容。【前端】文章目录 业务背景 用户在输入【金额】字段时,实时展示千分位格式。 业务分析 从需求来看,我们需要实现一个【千分位】组件,并且该组件允许在【表单】视图中使用。 扩展实现:该组件虽然仅要求在【表单】中使用,但也可以在【搜索】中使用完全相同的实现,因此这里我们在注册时会增加【搜索】视图,将【千分位】组件应用在【搜索】中。对于【表格】、【详情】和【画廊】来说,该组件是没有【输入】行为的展示组件,在这里我们不进行演示。 准备工作 此处你应该已经在某个业务模型下,可以完整执行当前模型的全部【增删改查】操作。 业务模型定义 (以下仅展示本文章用到的模型字段,忽略其他无关字段。) 名称 API名称 业务类型 是否多值 长度(单值长度) 编码 code 文本 否 128 名称 name 文本 否 128 金额 money 金额 否 – 创建组件、元件 准备工作完成后,我们需要根据【业务背景】确定【组件】以及【元件】相关信息,并在【界面设计器】中进行创建。 以下操作过程将省略详细步骤,仅展示可能需要确认的关键页面。 创建千分位组件 创建千分位元件 启动SDK工程进行组件基本功能开发 (npm相关操作请自行查看SDK工程中内置的README.MD) 关键点详解 数据交互类型的字段组件(以下简称展示组件)与仅展示类型的字段组件(以下简称交互组件)有一些差别。 通常情况下,在展示组件中仅需使用value属性即可展示相关内容。在交互组件中除了value用于展示外,还需使用change、focus以及blur处理用户输入时的基本交互逻辑。 数据交互方法主要功能说明: change方法:当值发生变更时调用,根据字段相关配置将值回填至表单中。 focus方法:当组件获取焦点时调用,记录当前值,并在调用blur方法时进行处理。 blur方法:当前组件失去焦点时调用,根据focus方法记录的值,进行失焦触发逻辑的执行。 这里的三个数据交互方法仅仅是对用户行为的抽象,而并非限定其使用场景。 通常来说,这三个方法的调用顺序为:focus –> change –> blur。 如在日期时间组件中,面板打开时调用了focus方法,面板值发生变更时,调用了change方法,面板关闭时调用了blur方法。 如在地图组件中,选中地图上的某个点时仅会调用change方法,用户交互上并不能体现出focus和blur的行为。因此对于这个组件而言,只会有change方法被执行。 代码实现参考 PS:oio-input-number样式必须升级到4.6.x以上的最新版本才支持 Thousandth.vue <template> <a-input-number class=”oio-input-number” :value=”inputValue” :formatter=”formatter” :parser=”parser” @update:value=”change” @focus=”focus” @blur=”blur” /> </template> <script lang=”ts”> import { InputNumber as AInputNumber } from ‘ant-design-vue’; import { computed, defineComponent } from ‘vue’; export default defineComponent({ name: ‘Thousandth’, components: { AInputNumber }, props: { value: { type: [String, Number] }, change: { type: Function }, focus: { type: Function }, blur: { type: Function } }, setup(props) { const inputValue = computed(() => { return props.value; }); const formatter = (value) => { return <span class="hljs-subst">${value}</span>.replace(/\B(?=(\d{3})+(?!\d))/g, ‘,’); }; const parser = (value) => { return value.replace(/\$\s?|(,*)/g, ”); }; return { inputValue, formatter, parser }; } }); </script> FormMoneyThousandthFieldWidget.ts import { FormFieldWidget, ModelFieldType, SPI, ViewType } from ‘@kunlun/dependencies’; import Thousandth from ‘./Thousandth.vue’; @SPI.ClassFactory( FormFieldWidget.Token({ viewType: [ViewType.Form, ViewType.Search], ttype: ModelFieldType.Currency,…

    2023年11月1日
    96800

Leave a Reply

登录后才能评论