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

场景

描述

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

如何实现

第一步

在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

相关推荐

  • 前端打包文件上传到oss

    打包dist文件上传到oss教程 1: 确保boot工程里面安装了「webpack-aliyun-oss」依赖, 如果没有安装,可以手动安装下 2: package.json -> devDependencies -> {"webpack-aliyun-oss": "0.5.2"} 3: 在vue.config.js文件中添加对应的plugin // vue.config.js文件 // 新增代码 let BASE_URL = '/'; const { DEPLOY, OSS_REGION, OSS_DIST, OSS_URL, OSS_ACCESS_KEY_ID, OSS_ACCESS_KEY_SECRET, OSS_BUCKET } = process.env; const UNIQUE_KEY = Math.random(); switch (DEPLOY) { case 'online': BASE_URL = `${OSS_URL}${UNIQUE_KEY}/`; break; default: BASE_URL = '/'; } module.exports = { …原先的代码, publicPath: BASE_URL, plugins: [ …原先的插件, DEPLOY === 'online' ? new WebpackAliyunOss({ from: ['./dist/**/**', '!./dist/**/*.html'], // build目录下除html之外的所有文件 dist: `${OSS_DIST}/${UNIQUE_KEY}`, // oss上传目录 region: OSS_REGION, // 地区, 比如 oss-cn-hangzhou accessKeyId: OSS_ACCESS_KEY_ID, accessKeySecret: OSS_ACCESS_KEY_SECRET, bucket: OSS_BUCKET, timeout: 1200000, deleteOrigin: true, deleteEmptyDir: true, overwrite: true }) : () => {} ] } 4: 在vue.config.js同级目录下面新增「.env」文件, 写入对应的配置, 配置对应的值按照自己的oss配置来 DEPLOY=online OSS_BUCKET=xxx OSS_DIST=/oinone/product OSS_URL=https://xxxxxx/oinone/product/ OSS_REGION=oss-cn-hangzhou OSS_ACCESS_KEY_ID=xxxx OSS_ACCESS_KEY_SECRET=xxxx

    2023年11月1日
    1.3K00
  • 【动作】-路由动作跳转后如何主动刷新页面数据

    介绍 当我们使用多tab组件的时候,如果一个viewAction已经打开了一个tab页,再次用该viewAction打开页面的时候,会发现不会根据路由上的业务参数(如详情和编辑页的id参数)主动刷新数据,这个时候可以通过以下方法解决该问题 // 该方法可以在进入新路由页面后刷新数据,推荐将该方法放到工具类 function refreshViewAction(action: any) { const onRefreshTabWithActive = (manager: MultiTabsManager, instance: MultiTabInstance) => { // 进入路由后刷新页面数据 manager.refresh(instance.key); manager.clearOnActive(onRefreshTabWithActive); }; MultiTabsManager.INSTANCE.onActive(onRefreshTabWithActive); executeViewAction(action); } 将原本调用executeViewAction的方法改为refreshViewAction 如果需要扩展executeViewAction的其他入参请自行拓展refreshViewAction的入参

    2024年6月18日
    1.4K00
  • 如何通过浏览器开发者工具提高调试效率

    1.通过vue devtool查看vue组件和oinone组件的信息 平台字段、动作、视图组件都是以Widget结尾的,可以通过关键字快速找到组件 安装vue devtool插件 chrome安装最新版的vue devtool插件 谷歌应用商店插件地址,隐藏窗口需要在扩展程序的详情页额外设置才能使用该插件 安装好插件后,可以通过插件选中html页面中的元素查看相关信息 相关特性了解 组件自动创建的vue组件以组件的class类名命名,据此特性可以得出自定义组件的时候,可继承该命名的父类 一般oinone的组件以Widget后缀命名,也推荐大家也以此为后缀,方便在vue调试面板快速看出哪些是oinone组件 选中oinone组件后可以在右侧面板看到相关的组件信息,部分属性介绍 template属性为dsl的配置 activeRecords、formData、rootData、parentData、dataSource等属性为常用数据属性 action为动作的元数据 field为字段的元数据 2.直接在浏览器开发者工具的源码处调试源码 打开浏览器开发者工具,进入标签页源代码/来源(英文版为Source),win系统用快捷键ctrl+O,mac系统用快捷键cmd+O, 可以打开文件搜索面板,通过关键字搜索文件名找到代码文件,可直接在里面debug调试或者查看执行逻辑

    2024年9月9日
    1.6K00
  • 如何实现页面间的跳转

    介绍 在日常的业务中,我们经常需要在多个模型的页面之间跳转,例如从商品的行可以直接点击链接跳转到类目详情,还有查看该订单发起的售后单列表,这里将给大家展示如何在oinone中如何实现这些功能。 方法一、通过界面设计器的无代码能力配置 表格行跳转到表单页/详情页 拖入一个跳转动作到表格行,保存动作后,在左侧的动作属性面板底部有个请求配置,里面的上下文属性就是配置跳转参数的地方,点击添加按钮可以增加一行参数 点击添加按钮后,可以看到新增了一行,行内有2个输入框,左侧输入框为目标视图模型的字段,右侧输入框为当前视图模型的表达式 注意 表达式中activeRecord关键字代表当前行的数据对象 “上下文”相关知识点 当前页面的模型和跳转后的页面模型相同的情况下,会字段带上当前行数据的id作为路由参数 上下文是从当前页面跳转到下个页面带的自定义参数 上下文会作为跳转后的页面数据加载函数的入参,后端的该函数需要根据该条件查询到数据返回给前端,典型的例子就是编辑页,根据id查询对象的其他字段信息返回 跳转后页面的数据加载函数可以在动作场景的时候选择加载函数,也可以在页面的加载函数处设置 方法二、通过低代码方式在自定义代码中调用 oinone提供了内置函数executeViewAction实现该功能 import { DefaultComparisonOperator, executeViewAction, QueryExpression, RuntimeViewAction, ViewActionTarget, ViewType } from '@kunlun/dependencies'; export class JumpActionWidget { protected goToObjectView() { executeViewAction( { viewType: ViewType.Form, moduleName: 'resource', model: 'resource.ResourceCountry', name: 'redirectUpdatePage', target: ViewActionTarget.Router } as RuntimeViewAction, undefined, undefined, { // 此处为id参数,目前只有表单和详情页需要 id: '12223', // 此处为上下文参数,context内对象的key是目标页面需要传递的默认值 context: JSON.stringify({code: 'xxx'}), // 此处为跳转后左侧菜单展开选中的配置 menu: JSON.stringify({"selectedKeys":["国家"],"openKeys":["地址库","地区"]}) } ); } protected goToListView() { const searchConditions: QueryExpression[] = []; searchConditions.push({ leftValue: ['countryCode'], // 查询条件的字段 operator: DefaultComparisonOperator.EQUAL, right: 'CN' // 字段的值 }); executeViewAction( { viewType: ViewType.Table, moduleName: 'resource', model: 'resource.ResourceCity', name: 'resource#市', target: ViewActionTarget.OpenWindow } as RuntimeViewAction, undefined, undefined, { // searchConditions相当于domain,不会随页面搜索项重置动作一起被清空 searchConditions: encodeURIComponent(JSON.stringify(searchConditions)), // searchBody的字段会填充搜索区域的字段组件,会随页面搜索项重置动作一起被清空 searchBody: JSON.stringify({code: 'CN'}), menu: JSON.stringify({"selectedKeys":["国家"],"openKeys":["地址库","地区"]}) } ); } } 扩展知识点 为什么executeViewAction跳转到的新页面不是入参的moduleName属性对应的模块? 答:跳转后所在的模块优先级为: 第一个入参的resModuleName属性对应的模块 执行executeViewAction时所在的模块 第一个入参的moduleName属性对应的模块 如何快速获取选中菜单的值? 答:先通过页面菜单手动打开页面,然后在浏览器自带调试工具的控制台执行decodeURIComponent(location.href),其中的menu参数就是我们需要的值

    2024年5月13日
    3.0K00
  • 表格字段API

    BaseTableFieldWidget 表格字段的基类. 示例 class MyTableFieldClass extends BaseTableFieldWidget{ } 内置常见的属性 dataSource 当前表格数据 rootData 根视图数据 activeRecords 当前选中行 userPrefer 用户偏好 width 单元格宽度 minWidth 单元格最小宽度 align 内容对齐方式 headerAlign 头部内容对齐方式 metadataRuntimeContext 当前视图运行时的上下文,可以获取当前模型、字段、动作、视图等所有的数据 urlParameters 获取当前的url field 当前字段 详细信息 用来获取当前字段的元数据 model 当前模型 详细信息 用来获取当前模型的元数据 view 当前视图 详细信息 界面设计器配置的视图dsl disabled 是否禁用 详细信息 来源于界面设计器的配置 invisible 当前字段是否不可见 详细信息 来源于界面设计器的配置,true -> 不可见, false -> 可见 required 是否必填 详细信息 来源于界面设计器的配置,如果当前字段是在详情页,那么是false readonly 是否只读 详细信息 来源于界面设计器的配置,如果当前字段是在详情页、搜索,那么是false label 当前字段的标题 详细信息 用来获取当前字段的标题 内置常见的方法 renderDefaultSlot 渲染单元格内容 示例 @Widget.Method() public renderDefaultSlot(context): VNode[] | string { // 当前单元格的数据 const currentValue = this.compute(context) as string[]; return [createVNode('div', { class: 'table-string-tag' }, currentValue)]; } renderHeaderSlot 自定义渲染头部 示例 @Widget.Method() public renderHeaderSlot(context: RowContext): VNode[] | string { const children = [createVNode('span', { class: 'oio-column-header-title' }, this.label)]; return children; } getTableInstance 获取当前表格实例(vxe-table) getDsl 获取界面设计器的配置

    2023年11月16日
    1.2K00

Leave a Reply

登录后才能评论