You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JSON Forms数字字段输入1.报错、1.0自动删.0的解决方法问询

JSON Forms数字字段输入问题解决方案

问题概述

使用JSON Forms时遇到数字类型字段的两个核心问题:

  • 输入1.05这类数值过程中,输入到1.阶段会立即触发验证错误
  • 输入1.0后,.0部分会被自动格式化删除

尝试过调整AJV参数、移除AJV实例、修改@change钩子等操作,均未解决问题。需求是将验证/自动修正逻辑改为change事件触发(而非实时input触发),或找到其他可行方案。

相关代码配置

Forms组件

<json-forms
    :schema="schema"
    :uischema="null"
    :data="localData"
    :renderers="renderers"
    :ajv="ajv"
    @change="(evt) => localData = evt.data"
/>

Schema定义

{
   "type": "object",
   "default": {},
   "properties": {
      "nir": {
         "type": "number",
         "title": "NIR"
      },
      "rgb": {
        "type": "number",
        "title": "RGB"
      }
  }
}

AJV配置

ajv: Ajv = createAjv(
    {
        useDefaults: true,
        multipleOfPrecision: 2,
    }
);

解决方案:自定义数字渲染器

JSON Forms默认数字组件会在input事件实时处理验证和值格式化,要修改触发时机,需自定义数字渲染器替换默认组件,将逻辑绑定到change事件(即输入框失去焦点时)。

1. 编写自定义数字渲染器(Vue版本)

<template>
  <div class="custom-number-control">
    <label>{{ label }}</label>
    <input
      type="text"
      :value="displayValue"
      @change="onInputChange"
      :class="{ 'input-error': hasErrors }"
    />
    <span v-if="hasErrors" class="error-text">{{ errorMessage }}</span>
  </div>
</template>

<script>
import { rendererProps } from '@jsonforms/vue';

export default {
  name: 'CustomNumberRenderer',
  props: rendererProps,
  computed: {
    label() {
      return this.uischema.label || this.schema.title || '';
    },
    displayValue() {
      // 处理值显示:整数格式的数字强制显示为x.0,避免.0被自动删除
      if (typeof this.data === 'number') {
        return Number.isInteger(this.data) ? `${this.data}.0` : String(this.data);
      }
      return '';
    },
    hasErrors() {
      return this.errors.some(err => err.path === this.path);
    },
    errorMessage() {
      const fieldError = this.errors.find(err => err.path === this.path);
      return fieldError ? fieldError.message : '';
    }
  },
  methods: {
    onInputChange(e) {
      const inputVal = e.target.value.trim();
      let newValue;

      // 处理输入为空的情况
      if (!inputVal) {
        newValue = undefined;
      } 
      // 处理输入以.结尾的情况,暂时转换为带0的小数(如"1."转为1.0)
      else if (inputVal.endsWith('.')) {
        newValue = parseFloat(`${inputVal}0`);
      } 
      // 正常数字转换
      else {
        newValue = parseFloat(inputVal);
      }

      // 触发JSON Forms的数据更新
      this.handleChange(this.path, newValue);
    }
  }
};
</script>

<style scoped>
.custom-number-control {
  margin-bottom: 1rem;
}
.input-error {
  border-color: #dc3545;
}
.error-text {
  color: #dc3545;
  font-size: 0.875rem;
}
</style>

2. 注册自定义渲染器

将自定义渲染器替换默认的数字渲染器,确保JSON Forms使用新组件:

import { vanillaRenderers } from '@jsonforms/vue-vanilla';
import CustomNumberRenderer from './CustomNumberRenderer.vue';

// 替换默认数字渲染器
export const renderers = [
  ...vanillaRenderers,
  {
    tester: (schema, uischema, context) => {
      // 匹配数字类型的字段
      return schema.type === 'number' ? 10 : -1;
    },
    renderer: CustomNumberRenderer
  }
];

方案说明

  • 验证与值更新逻辑绑定到change事件,只有当输入框失去焦点时才会触发数据更新和验证,避免输入过程中出现错误提示
  • 自定义值显示逻辑,强制整数格式的数字显示为x.0,解决.0被自动删除的问题
  • 处理输入1.这类中间状态,自动补全为1.0后再转换为数字,既符合用户输入习惯,也满足schema的数字类型要求

内容的提问来源于stack exchange,提问作者TheSaGe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 04:36:33