表格新增空行或者按照数据如何复制行

场景

描述

新增按钮点击后表格出现空行,不带业务数据,需要有行内编辑

如何实现

第一步

在layout目录下新增copyTable组件,组件代码如下

import { BaseElementWidget, SPI, TableWidget, Widget } from '@kunlun/dependencies';
import { OioNotification } from '@kunlun/vue-ui-antd';

@SPI.ClassFactory(BaseElementWidget.Token({ widget: 'copy-table-row' }))
export class CopyTableWidget extends TableWidget {
    @Widget.BehaviorSubContext(Symbol("$$TABLE_COPY_CB"), {})
    private tableCopySub;

    @Widget.BehaviorSubContext(Symbol("$$TABLE_DELETE_CB"))
    private tableDeleteSub;

    @Widget.Reactive()
    @Widget.Provide()
    protected get editorMode(): any {
        return 'manual'
    }

    public async copyRowData(row,currentRow) {
        // 获取vxetable 实例
        const tableRef = this.getTableInstance()!.getOrigin();
        if (tableRef) {
            // 有复制未保存数据,如何处理?
            const insertData = tableRef.getInsertRecords();
            if(insertData.length > 0){
                OioNotification.warning("警告","请检查未保存数据!")
                return;
            }

            const { row: newRow } = await tableRef.insertAt(row,currentRow)
            // 插入一条数据并触发校验, 其中字段名称可以替换
            await tableRef.setEditCell(newRow, 'city')
        }
    }

    public async deleteRowData(row) {
        // 获取vxetable 实例
        const tableRef = this.getTableInstance()!.getOrigin();
        if (tableRef) {
            // 有复制未保存数据,如何处理?
            console.log(row, 'remove row')
            tableRef.remove(row)
            // 插入一条数据并触发校验
        }
    }

    async mounted() {
        super.mounted();
        this.tableCopySub.subject.next({copyCb: (row,currentRow) => this.copyRowData(row,currentRow)})
        this.tableDeleteSub.subject.next({deleteCb: (row) => this.deleteRowData(row)})
    }
}

第二步

在action目录下覆盖新增按钮或者复制行按钮;代码如下

import {ActionWidget, ClickResult, ReturnPromise, SPI, Widget} from "@kunlun/dependencies";

@SPI.ClassFactory(
  ActionWidget.Token({
    model: 'resource.k2.Model0000001211', // 替换对应模型
    name: 'uiView57c25f66fac9439089d590a4ac47f027' // 替换对应action的name
  })
)
export class CopyRow extends ActionWidget{
  @Widget.BehaviorSubContext(Symbol("$$TABLE_COPY_CB"))
  private tableCopySub;

  private tableCopyCb;

  @Widget.Method()
  public clickAction(): ReturnPromise<ClickResult> {
    // 按照某一条数据复制行, 按钮在行内
    // let data = JSON.parse(JSON.stringify(this.activeRecords?.[0]));
    // 复制行删除id
    // if(data) {
    //   delete data.id
    //   delete  data['_X_ROW_KEY']
    // }
    // console.log(data, 'datatatatat')
    // this.tableCopyCb(data,this.activeRecords?.[0])

    // 全局新增,不带默认数据
    this.tableCopyCb({},null)
  }

  mounted() {
    super.mounted()
    this.tableCopySub.subscribe((value) => {
      if(value) {
        // debugger
        this.tableCopyCb = value.copyCb
      }
    })
  }
}

第三步

替换对应的表格layout

// 替换第二个入参的模型和动作
const registerGlobalTableLayout = () => {
    return registerLayout(`<view type="TABLE">
    <pack widget="group">
        <view type="SEARCH">
            <element widget="search" slot="search" slotSupport="field" />
        </view>
    </pack>
    <element widget="actionBar" slot="actionBar" slotSupport="action">
        <xslot name="actions" slotSupport="action" />
    </element>
    <pack widget="group" slot="tableGroup">
        <element widget="copy-table-row" slot="table" slotSupport="field">
            <element widget="expandColumn" slot="expandRow" />
            <xslot name="fields" slotSupport="field" />
            <element widget="rowActions" slot="rowActions" slotSupport="action" />
        </element>
    </pack>
</view>`, { viewType: ViewType.Table, model: 'resource.k2.Model0000001211' }) 
}

registerGlobalTableLayout()

补充

  1. 新增空行后的动作可以根据行内数据配置显隐,比如有无id配置是编辑还是保存
  2. 新增后怎么开启行内编辑?可以进入界面设计器选中表格字段,开启行内编辑,新增行后会默认有行内编辑

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

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

(0)
王海明的头像王海明数式管理员
上一篇 2024年7月12日 pm3:34
下一篇 2024年7月15日 pm3:59

相关推荐

  • 前端-如何修改指定页面的内组件的css样式

    为组件加自定义class,用该class作为父选择器写特定的css样式 以form为例,自定义了以下class <view/>标签的表单视图(FormView)组件 <element/>标签的form(FormWidget)组件 <element/>标签的actionBar(ActionBarWidget)组件 import { registerLayout, ViewType } from '@kunlun/dependencies'; export const install = () => { registerLayout( ` <view type="FORM" class="my-form-view"> <element widget="form" slot="form" class="my-form-widget"> <xslot name="fields" slotSupport="pack,field" /> </element> <element widget="actionBar" slot="actionBar" class="my-action-bar" slotSupport="action" > <xslot name="actions" slotSupport="action" /> </element> </view> `, { viewType: ViewType.Form, model: 'resource.k2.Model0000000109', actionName: 'uiViewb2de116be1754ff781e1ffa8065477fa' } ); }; install(); 查看修改后的页面html结构 编写样式的css .my-form-view .oio-form { /** TODO **/ } .my-form-widget .oio-row { /** TODO **/ } .my-action-bar .oio-col { /** TODO **/ }

    2024年6月17日
    1.2K00
  • oinone的rsql与传统sql语法对照表

    rsql sql 描述 field01 == "name" field01 = "name" 等于 field01 != "name" field01 != "name" 不等于 field01 =gt= 1 field01 > 1 大于 field01 =ge= 1 field01 >= 1 大于等于 field01 =lt= 1 field01 < 1 小于 field01 =le= 1 field01 <= 1 小于等于 field01 =isnull=true field01 is null 字段为null field01 =notnull= 1 field01 is not null 字段不为null field01 =in= ("foo") field01 in ("foo") 多条件 field01 =out= ("foo") field01 not in ("foo") 不在多条件中 field01 =cole= field02 field01 = field02 字段作为查询参数 field01 =colnt= field02 field01 != field02 字段作为查询参数 field01 =like="foo" field01 like "%foo%" 全模糊匹配,rsql语法中无需拼接通配符”%“ field01 =starts="foo" field01 like "foo%" 前缀模糊匹配,rsql语法中无需拼接通配符”%“ field01 =ends="foo" field01 like “%foo" 后缀模糊匹配,rsql语法中无需拼接通配符”%“ field01 =notlike="foo" field01 not like "%foo%" 全模糊不匹配,rsql语法中无需拼接通配符”%“ field01 =notstarts="foo" field01 not like "foo%" 前缀模糊不匹配,rsql语法中无需拼接通配符”%“ field01 =notends="foo" field01 not like “%foo" 后缀模糊不匹配,rsql语法中无需拼接通配符”%“ field01 =has=(ENUM_NAME1, ENUM_NAME2) 有多值枚举中的几个值 field01 =hasnt=(ENUM_NAME1,ENUM_NAME2) 没有多值枚举中的几个值 field01 =bit=ENUM_NAME1 有二进制枚举中的单个值 field01 =notbit=ENUM_NAME1 没有二进制枚举中的单个值 前端代码中使用工具类拼接rsql 该工具类在oinone的前端基础框架中提供 import { Condition } from '@kunlun/dependencies'; const rsqlCondition = new Condition('field01').equal('foo') .and(new Condition('field02').in(['bar'])) .and(new Condition('field03').notIn(['foo'])) .or(new Condition('field04').greaterThanOrEuqalTo(12)) .or(new Condition('field05').like('foo')) .or(new Condition('field06').notStarts('bar')) .or(new Condition('field07').isNull()) .or(new Condition('field08').notNull()) .and(new Condition('field09').bitEqual('BIT_ENUM_1')) .and(new Condition('field10').bitNotEqual('BIT_ENUM_2')) .and(new Condition('field11').has('ENUM_NAME_1')) .and(new Condition('field12').hasNot(['ENUM_NAME_2', 'ENUM_NAME_3'])); const rsqlStr = rsqlCondition.toString();…

    2023年11月1日
    4.2K00
  • 如何自定义表格单元格样式

    介绍 OinOne的表格是基于Vxe-Table实现的,我们将Vxe-table内置的关于单元格样式的方法、属性开放到了表格组件TableWidget上 Vxe-Table相关文档 vxe-table的单元格样式 vxe-table的单元格动态样式 单元格样式 行的样式、单元格样式,表头的样式、表尾的样式、全部都可以完全自定义,通过设置 cellClassName、headerCellClassName、rowClassName …等参数 (注:当自定义样式之后可能会覆盖表格的样式,比如选中行..等,记得自行处理好相关样式) 单元格动态样式 行的动态样式、单元格动态样式,表头的动态样式、表尾的动态样式、可以通过设置 cellStyle、headerCellStyle、rowStyle …等参数 (注:当自定义样式之后可能会覆盖表格的样式,比如选中行..等,记得自行处理好相关样式) 示例代码 这里仅演示cellClassName和cellStyle,其他方法的出入参数请参考上面的Vxe-Table文档 import { BaseElementWidget, SPI, TableWidget, ViewType, Widget } from '@kunlun/dependencies'; @SPI.ClassFactory(BaseElementWidget.Token({ viewType: ViewType.Table, widget: 'CustomStyleTableWidget', })) export class CustomStyleTableWidget extends TableWidget { @Widget.Method() protected cellClassName({ row, rowIndex, $rowIndex, column, columnIndex, $columnIndex }) { if (column.field === 'field00019') { return `demo-cell-${column.field}`; } return ''; } @Widget.Method() protected cellStyle({ row, rowIndex, $rowIndex, column, columnIndex, $columnIndex }) { if (column.field === 'field00019') { return { backgroundColor: '#f60', color: '#ffffff' }; } return ''; } } 效果预览

    2024年10月30日
    1.3K00
  • oio-checkbox 对选框

    API 属性 Checkbox 参数 说明 类型 默认值 版本 autofocus 自动获取焦点 boolean false checked(v-model:checked) 指定当前是否选中 boolean false disabled 失效状态 boolean false indeterminate 设置 indeterminate 状态,只负责样式控制 boolean false value 与 CheckboxGroup 组合使用时的值 boolean | string | number – 事件 事件名称 说明 回调参数 版本 change 变化时回调函数 Function(e:Event) –

    2023年12月18日
    91900
  • TableWidget 与 FormWidget 浅析

    前言:本文主要聚集于 TableWidget和 FormWidget,对两者以外的内容不做赘述。 TableWidget和 FormWidget作为一个基本的渲染模块与 Mask等不同,TableWidget与 FormWidget有着明确的目的,比如 TableWidget就是作为一个表格视图,这种名称中可以看得出来。其将表格的一系列能力聚拢,如单元格,行列选择排序,翻页等等; TableWidget 我们使用表格到底是在使用什么? 在我们讲述渲染流程前,我们需要提一个问题,在我们使用表格组件时,我们在使用什么,换而言之,我们对表格组件中关注的是什么?应该说我们更关注的是表格所展示的数据。TableWidget或者说整个低代码其实解决的就是这个问题,让我们可以很方便的展示数据。不用关心一些细枝末节 TableWidget 的渲染 TableWidget在整个渲染流程中的负责组装各种 Vue 组件所需要的核心数据或事件回调并传递给其绑定的 Vue 组件即 DefaultTable,如 allowRowClick,rowClickMode等等,这些值会作为 Props 传递给 DefaultTable,DefaultTable则一定意义上充当了一个桥接层,主要做了两件事,处理 Props, 处理 Slot,TableWidget传递给 DefaultTable的 Props 会经过 DefaultTable再次组合,创建新的 Props,同时根据当前的 Props 判断是否有必要新增一些 slot,比如 OioPagination组件是否需要渲染就取决于 Props.showPagination 的值,经过 DefaultTable的处理后, props与 slot会进一步交给 OioTable进行渲染,OioTable则会进一步聚合处理,比如如果没有 defaultSlot则进行空值的渲染,如果存在 footSlot则会构建一个包裹层去包裹它。这些组件协同完成了一个表格的结构,而我们真正关心的数据则由一个个 BaseTableColumnWidget渲染。BaseTableColumnWidget的渲染过程类似于 TableWidget,其负责组装 DefaultTableColumn渲染所需要的 props,然后交给 OioTableColumn进行实际渲染。并且会有多种基于 BaseTableColumnWidget的 widget通过重写 renderDefaultSlot,renderEditSlot,renderContentSlot,renderHeaderSlot等几个 props 实现不同状态,不同类型等组件的渲染。通过 TableWidget与 BaseTableColumnWidget相结合, Table 页面完成了主体框架与内容的渲染。而当数据完成渲染后,不可避免的会有数据交互,比如分页,排序,过滤等,这些交互都由 TableWidget与 BaseTableColumnWidget共同完成。比如排序翻页等,TableWidget会将事件作为 props 向下注入,当事件被调用,TableWidget会进行处理,比如发起请求,或者对内部数据排序等。而除了数据的展示,还有一些动作,即 Action ,Action 被触发时会按照内部的配置进行工作,比如编辑时,将获取 activeRecord,随后触发 Table 的编辑。 TableWidget就是这样去渲染出了一个完整的表格页面。能够完成数据的增删改查等操作 FormWidget FormWidget与 TableWidget一样,也是作为一个渲染模块,但是它与 TableWidget不同的是,FormWidget是作为一个表单视图,其将表单的一系列能力聚拢,如表单提交,表单校验,表单重置等等。其重点在于对数据的增改。所以在提供的能力上也有区别,比如 FormWidget没有提供翻页,排序,过滤等能力,因为这些能力属于表格的能力,而 FormWidget则更关注于表单的能力。提供了数据的存储,提交,校验等能力 Form 在渲染时流程与 Table 大同小异,其同样为三层结构 FormWidget => DefaultForm => FormFieldWidget 一层层向下渲染,不同的在于 FormWidget 更多的关注点在于维护其内部的 FormData 这是整个表单页面所围绕的东西,当页面上的控件发生变化,其变更的值会被收集到 FormData 中,并在后续中使用。同时在编辑已有数据场景下,Form 会将数据加载到 FormData,随后下放给 FormFiledWidget。 异同之处 从介绍中可以看出,Table 侧重于数据的查询展示,Form 则侧重于数据的变动处理,但是抽象的看其核心其实是同一套逻辑,即数据的存储与展示,中间或许会有对数据的某些处理,但是并不是本质上的区别,两者在核心理念上是一致的,即让使用者只需要关心数据本身,而不需要关注于繁琐的视图构造,这是整个低代码甚至前端的发展方向。

    2025年3月25日
    75800

Leave a Reply

登录后才能评论