MrBr / antd-zod

Antd Zod validation
MIT License
32 stars 6 forks source link

Compatible with antd component #9

Closed cnpap closed 7 months ago

cnpap commented 8 months ago

antd pro components

When this table component is added or modified, the field name obtained inside the component is in the format of ${key}.${field}. For example, there is a piece of data called {id: 123, name: 'qwe'}, then when the name changes, the obtained field name is 123.name

codesandbox

I think this change does not require a new API, keep it simple, then this is my implementation suggestion

import { ZodRawShape } from "zod";
import { RuleRender } from "rc-field-form/lib/interface";
import { AntdFormZodSchema } from "../types";
import validateFields from "./validateFields";
import prepareValues from "./prepareValues";

interface CreateSchemaFieldRuleOptions {
  ignorePrefix?: boolean;
}

const createSchemaFieldRule =
  <T extends ZodRawShape>(schema: AntdFormZodSchema<T>, options: CreateSchemaFieldRuleOptions = {}): RuleRender =>
    ({ getFieldsValue }) => ({
      validator: (rule) =>
        new Promise(async (resolve, reject) => {
          // AsyncValidator adds field - rc-field-form type isn't correct
          // https://github.com/search?q=repo%3Ayiminghe%2Fasync-validator%20fullField&type=code
          let { field } = rule as { field: string };
          if (options.ignorePrefix) {
            const indexOf = field.indexOf(".");
            if (indexOf !== -1) {
              field = field.slice(indexOf + 1);
            }
          }
          const values = getFieldsValue();
          const errors = await validateFields<T>(
            schema,
            prepareValues(schema, values),
          );

          if (!!errors && errors[field]) {
            reject(errors[field]);
            return;
          }

          resolve(undefined);
        }),
    });

export default createSchemaFieldRule;
cnpap commented 8 months ago

If this idea is ok, then please review the pr #10

MrBr commented 8 months ago

If I understood correctly the antd pro table adds a prefix to field property in validator (being a row identifier) but expects error path to be without the prefix? This doesn't seem right, maybe there's something more.

There are some specifics when it comes to the list validation in the normal Form. For example, the input list must be wrapped with Form.Item in order for the validation to work properly, see it here https://github.com/MrBr/antd-zod/blob/main/stories/basic.stories.tsx#L102

Can you double check if this is really the case?

cnpap commented 8 months ago

Ok, after get off work I will further think and test based on the use cases you provided.

cnpap commented 8 months ago

Work was too heavy yesterday. I have tested it. First of all, it works through Form.List. My colleagues have switched many components that use edit table to Form.List and now they work normally.

image

However, the edit table of pro component has some special features. It uses the id at the same level as the data as the prefix of the key. This PR only responds to this emergency situation. Now we should have three processing methods.

cnpap commented 8 months ago

Maybe Form.List and potentially edit table should provide use cases in readme.md, which would help to reassure potential users

MrBr commented 8 months ago

In this case, if pro components require some specific behaviour I'd like to create a new function for it. something like createSchemaProFieldRule or createSchemaProTableRule.

This will leave the old API as is and provide a new functionality without the special case.

Possibly you can use createSchemaFieldRule under the hood.