react-admin icon indicating copy to clipboard operation
react-admin copied to clipboard

Validation in FormDataConsumer is not updated (taking previous validation) when selected option is updated in SelectInput.

Open aishahsofea opened this issue 4 years ago • 5 comments

What you were expecting: I am expecting that validation will change according to the selected value in SelectInput dropdown.

What happened instead: It validates against the previously selected value.

Steps to reproduce:

  1. Create new comment. Click on Post SelectInput and a dropdown will appear. Select the last post (id = 1).
  2. In the field right below Post, write 'abcde', and we'll get validation error 'max 1 char'
  3. Now go back to Post and select the second last option (id = 2)
  4. Notice that the validation error is still 'max 1 char'
  5. Then, select last post (id = 1) again. Now we'll get validation error 'max 2 char' which is what we're supposed to get when selected id = 2.

Related code: Code is in PostReferenceInput.js I reproduced this issue in this codesandbox

import * as React from 'react';
import { Field } from 'redux-form';
import { maxLength, required } from 'ra-core';
import {
    ReferenceInput,
    SelectInput,
    FormDataConsumer,
    LongTextInput
} from 'react-admin';

import PostQuickCreateButton from './PostQuickCreateButton';
import PostQuickPreviewButton from './PostQuickPreviewButton';

class PostReferenceInput extends React.Component {
    constructor(props) {
        super(props);
        this.renderValue = this.renderValue.bind(this);
        this.validate = this.validate.bind(this);
    }
    validate(type) {
        if (type === 1) {
            return maxLength(1, 'max 1 char');
        } else if (type === 2) {
            return maxLength(2, 'max 2 char');
        }
    }

    renderValue() {
        return (
            <FormDataConsumer>
                {({ formData, ...rest }) => {
                    const type = formData.post_id && formData.post_id;
                    console.log(type);

                    return (
                        <LongTextInput
                            source="ruleValue"
                            label={type}
                            validate={this.validate(type)}
                        />
                    );
                }}
            </FormDataConsumer>
        );
    }

    render() {
        return (
            <React.Fragment>
                <ReferenceInput {...this.props}>
                    <SelectInput optionText="id" />
                </ReferenceInput>
                {this.renderValue()}

                <PostQuickCreateButton />
                {/* We use Field to get the current value of the `post_id` field */}
                <Field
                    name="post_id"
                    component={({ input }) =>
                        input.value && (
                            <PostQuickPreviewButton id={input.value} />
                        )
                    }
                />
            </React.Fragment>
        );
    }
}

export default PostReferenceInput;

Other information:

Environment

  • React-admin version: 2.8
  • Last version that did not exhibit the issue (if applicable): N/A
  • React version: 16.3
  • Browser: Chrome
  • Stack trace (in case of a JS error):

aishahsofea avatar Feb 20 '20 08:02 aishahsofea

Reproduced Same in v3 https://codesandbox.io/s/late-https-f2zce

JulienMattiussi avatar Mar 17 '20 10:03 JulienMattiussi

I'm not sure we can do something for this. Form validation is managed by react-final-form (or redux-form in v2). It seems they both don't care that a change made on a field can trigger a dynamic validation error on another field.

I tryed using multi validation functions instead of a unique validation function having multl messages, but it doesn't change the behaviour

JulienMattiussi avatar Mar 17 '20 11:03 JulienMattiussi

@JulienMattiussi is there any workaround (that probably ditches redux-form)?

aishahsofea avatar Apr 01 '20 04:04 aishahsofea

To circumvent this I am passing validateOnBlur={true} to the form, but that messed with my ImageInput validation because it never blurs. I guess it could help you if you don't have also an image in your form.

Rawphs avatar Jun 24 '20 15:06 Rawphs

I had same problem. And I prefer If you want to validate between multiple value use allValues field

validate={[
        required(),
        minValue(),
        ...
        anyCustom,
]}

//value: value of current input
//allValues : all values of current form
const anyCustom = (value, allValues) => {
    if (...) {
     return errorMessage : string
    }
    return undefined
}

duongthaicuong avatar Feb 25 '22 07:02 duongthaicuong