字段组件submit方法详解

场景介绍

在日常开发调试表单页的过程中,细心的小伙伴应该注意到,视图内的数据(通过vue调试工具看到的formData就是视图的数据)和最终通过服务端动作提交的数据不总是一致的,本文将带领大家解开疑惑。

为什么会出现这种现象?

出现这种情况都是当前模型上有关联关系字段的场景,以多对一(M2O)场景为例,由于当前模型的关联关系字段是通过字段配置中的referenceFields属性和当前模型的relationFields属性进行关联的,所以提交数据的时候只需要拿到relationFields配置的字段就可以了,没有必要再去多拿关联关系字段本身的数据。

结合业务场景说明

这里以商品模型和类目模型举例,商品模型内有个类目的m2o字段category和对应的relationFields字段categoryId,数据提交到后端的时候前端默认会根据字段配置只获取categoryId,而category的整个对象都不会被提交。

package pro.shushi.pamirs.demo.api.model;

import pro.shushi.pamirs.demo.api.model.DemoItemCategory;
import pro.shushi.pamirs.meta.annotation.Field;
import pro.shushi.pamirs.meta.annotation.Model;
import pro.shushi.pamirs.meta.base.common.CodeModel;

@Model.model(DemoItem.MODEL_MODEL)
@Model(displayName = "测试商品")
public class DemoItem extends CodeModel {

    private static final long serialVersionUID = -5104390780952631397L;

    public static final String MODEL_MODEL = "demo.DemoItem";

    @Field.String
    @Field(displayName = "商品名称")
    private String name;

    @Field.Integer
    @Field(displayName = "类目ID")
    private Long categoryId;

    @Field.many2one
    @Field.Relation(relationFields = {"categoryId"}, referenceFields = {"id"})
    @Field(displayName = "商品类目")
    private DemoItemCategory category;
}

前端是如何处理数据的

前端的字段组件提供了submit()方法来让我们可以有就会在提交数据的时候改变数据。

// 字段组件基类
export class BaseFormItemWidget<
  Value = unknown,
  Props extends BaseFormItemWidgetProps = BaseFormItemWidgetProps
> extends BaseDataWidget<Props> {
 /**
   * 数据提交的方法,例如:m2o字段user(假设其关系字段为userId)的值{id: 1, name: 'xxx'},但是实际后端数据只需要其中的id,所以用m2o对应的关系字段userId提交数据就可以了
   * @param submitValue
   */
  public submit(submitValue: SubmitValue): ReturnPromise<Record<string, unknown> | SubmitRelationValue | undefined> {
    return undefined;
  }
}

这里先以FormStringFieldSingleWidget组件处理密码类型的字段讲解。
密码一般在输入的时候是明文,为了提高提交到后端的安全性,可以将这个密码加密后再传到后端,后端再做进一步处理,这个场景中,视图中的密码和提交给后端的密码就出现了不一致的情况,

@SPI.ClassFactory(
  BaseFieldWidget.Token({
    viewType: [ViewType.Form, ViewType.Search],
    ttype: ModelFieldType.String
  })
)
export class FormStringFieldSingleWidget extends FormStringFieldWidget {
  public submit(submitValue: SubmitValue) {
    let finalValue = this.value;
    /**
     * 数据提交的时候,如果判断当前字段是否需要加密,需要加密的情况用encrypt函数做加密处理
     */
    if (this.crypto && finalValue) {
      finalValue = encrypt(finalValue);
    }
    return SubmitHandler.DEFAULT(this.field, this.itemName, submitValue, finalValue);
  }

注意:关系字段配置的透出字段只影响该字段的查询数据方法的返回值,不会因为此配置就在提交数据里加上这部分配置的字段

字段需要提交关联关系字段内的所有数据如何处理?

我们可以在自定义组件里覆写submit()方法,直接将this.value内的数据返回
这里以覆写多对多m2m字段为例

import {
  BaseFieldWidget,
  FormM2MFieldSelectWidget,
  ModelFieldType,
  SPI,
  SubmitValue,
  ViewType
} from '@kunlun/dependencies';

@SPI.ClassFactory(
  BaseFieldWidget.Token({
    viewType: ViewType.Form,
    ttype: ModelFieldType.ManyToMany,
    widget: 'Select',
    model: 'xxx.yyyyy',
    name: 'fileName01',
  })
)
export class MyFormO2MSubmitAllSelectFieldWidget extends FormM2MFieldSelectWidget {

  /**
   * 提交数据的方法
   * 重写后会将字段内所有数据都提交,默认的方法只会提交关联关系字段的数据
   * @param submitValue
   */
  public async submit(submitValue: SubmitValue) {
    // this.itemName是当前字段名称
    return { [this.itemName]: this.value };
  }
}

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

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

Like (0)
nation's avatarnation数式员工
Previous 2024年9月10日 am9:35
Next 2024年9月11日 am9:57

相关推荐

  • 前端低无一体使用教程

    介绍 客户在使用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.9K00
  • OioNotification 通知提醒框

    全局展示通知提醒信息。 何时使用 在系统四个角显示通知提醒信息。经常用于以下情况: 较为复杂的通知内容。 带有交互的通知,给出用户下一步的行动点。 系统主动推送。 API OioNotification.success(title,message, config) OioNotification.error(title,message, config) OioNotification.info(title,message, config) OioNotification.warning(title,message, config) config 参数如下: 参数 说明 类型 默认值 版本 duration 默认 3 秒后自动关闭 number 3 class 自定义 CSS class string –

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

    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日
    2.4K00
  • 如何提高自定义组件的开发效率

    引言 本文将通过前端的开发者模式带领大家提高自定义组件的开发效率 支持2024年9月6日之后用npm i安装的4.7.x之后的所有版本 介绍前端开发者模式 开发者模式的特性 浏览器控制台可以看到更多利于开发的日志输出 页面顶部状态栏消息模块的轮询接口,将只在页面刷新后请求一次,这样会减少开发阶段不必要的请求,以及解决后端断点调试的时候被消息轮询干扰的问题 页面视图的数据将不在走缓存,而是每次实时从base_view表里查询template字段获取,方便需要实时看通过xml修改的页面效果 如何进入开发者模式 通过在浏览器地址栏后追加;mode=dev刷新页面进入开发者模式,页面加载后可以在浏览器开发者工具的应用标签下的本地存储空间(即localStorage)中看到本标识的存储,如果想退出开发者模式可以手动清除该值 开发者模式的应用场景 1.通过控制台跳转到视图动作(ViewAction)的调试页面 页面刷新后,可以在浏览器开发者工具的控制台看到如下图的日志输出,直接点击该链接可以跳转到当前页面的调试链接弹窗视图动作、抽屉视图动作等以弹出层为展示效果的页面,之前的版本是无法进入调试链接查看的,现在可以在弹窗等视图动作点击后在控制台看到该链接点击进入调试页面 2.查看页面母版(mask)、布局(layout)的匹配情况 母版(mask)匹配结果布局(layout)匹配结果 3.查看视图组件(View)、字段组件(Field)、动作组件(Action)的匹配情况 通过浏览器开发者工具的控制台,我们可以看到每个视图、字段、字段匹配到的组件的class类名,这样我们就知道当前用的是那个组件,在自定义的时候可以在源码查看该组件类的实现代码,然后再选择是否继承该父类。另外我们在给组件定义SPI条件的时候,可以参考匹配入参和匹配结果内的属性。 匹配入参是当前元数据SPI的最全量注册条件 匹配结果是当前匹配到的组件的注册条件,一般情况下我们只需要在匹配结果的条件加上当前模型编码(model)、视图名称(viewName)、字段名称(name)、动作名称(actionName)等条件就可以完成自定义组件的覆盖。 在浏览器开发者工具的控制台,通过模型编码、视图名称、字段名称、动作名称等关键字快速搜索定位到需要查找的组件 控制台搜索快捷键:win系统通过ctrl+f,mac系统通过cmd+f 总结 在确保自定义部分代码最终正确被import导入到启动工程main.ts内的情况下,可以通过开发者模式在浏览器控制台打印的日志来排查组件未正确覆盖的问题。

    2024年9月6日
    2.1K00
  • 【前端】登录页面扩展点

    登录页面扩展点 场景 1: 登录之前需要二次确认框2: 前端默认的错误提示允许被修改3: 后端返回的错误提示允许被修改4: 登录后跳转到自定义的页面 方案 前端默认错误可枚举 errorMessages: { loginEmpty: '用户名不能为空', passwordEmpty: '密码不能为空', picCodeEmpty: '图形验证码不能为空', phoneEmpty: '手机号不能为空', verificationCodeEmpty: '验证码不能为空', picCodeError: '图形验证码错误', inputVerificationCodeAlign: '请重新输入验证码' } 登录按钮添加拓展点beforeClick、afterClick 代码 新增一个ts文件,继承平台默认的LoginPageWidget @SPI.ClassFactory(RouterWidget.Token({ widget: 'Login' })) export class CustomLoginPageWidget extends LoginPageWidget { constructor() { super(); // 修改前端默认的错误文案 this.errorMessages.loginEmpty = '登录用户名不能为空'; } /** * 用来处理点击「登录」之前的事件,可以做二次确定或者其他的逻辑 * 只有return true,才会继续往下执行 */ public beforeClick(): Promise<Boolean | null | undefined> { return new Promise((resolve) => { Modal.confirm({ title: '提示', content: '是否登录?', onOk: () => { resolve(true); } }); }); } /** * * @param result 后端接口返回的数据 * * 用来处理「登录」接口调用后的逻辑,可以修改后端返回的错误文案,也可以自定义 * * 只有return true,才会执行默认的跳转事件 */ public afterClick(result): Promise<any | null | undefined> { // if(result.redirect) { // 自定义跳转 //return false //} if (result.errorCode === 20060023) { result.errorMsg = '手机号不对,请联系管理员'; } return result; } }

    2023年11月1日
    1.4K00

Leave a Reply

Please Login to Comment