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

onBlur required

Open ekv88 opened this issue 8 years ago • 4 comments

I have a case where i validate onBlur={this.props.setValue(this.props.getValue());} / onExit Now only validation rule that i want to achieve is: Required / No empty text

And my input component code looks like:

<MyInput required name="req" title="Required input!" validationError="This field is required!" />

Now the problem is: Form will say that it's not valid and it would trigger onInvalidSubmit But input will never get anything in this.props.getErrorMessage() method it will stay null and because of that i can't catch error onSubmit

So i spent some time looking around and going through a code, and I found out that if I implement my component like this, it would WORK!:

<MyInput required name="req" title="Required input!" validationErrors={{"isDefaultRequiredValue":"This field is required!"}} />

My component and form code looks something like:

MyInput Component

import React from 'react';
import { propTypes, withFormsy } from 'formsy-react';

class MyInput extends React.Component {
  constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this)
    this.handleOnBlur = this.handleOnBlur.bind(this)
  }

handleOnBlur(event) {
        // Validate at Blur
        this.props.setValue(this.props.getValue());
        // Execute onBlur prop
        if (typeof this.props.onBlur === 'function') {
            this.props.onBlur(event);
        }
    }

    handleChange(event) {
        // Store validation but dont validate
        if(!this.props.isValid()){
            this.props.setValue(event.currentTarget.value);
        }else{
            this.props.setValue(event.currentTarget.value, false);
        }

        // Execute onChange prop
        if (typeof this.props.onChange === 'function') {
            this.props.onChange(event);
        }
    }
  render() {
    const errorMessage = this.props.getErrorMessage();
   
    return (
      <div>
        <label htmlFor={this.props.name}>{this.props.title}</label>
        <input
          onChange={this.handleChange}
          onBlur={this.handleOnBlur}
          value={this.props.getValue() || ''}
          name={this.props.name}
        />
        <span className='validation-error'>{errorMessage}</span>
      </div>
    );
  }
}

MyInput.propTypes = {
  ...propTypes,
};

export default withFormsy(MyInput);

MyFormsyForm

import React from 'react';
import ReactDOM from 'react-dom';
import Formsy from 'formsy-react';

// My Input
import MyInput from 'Input';

class App extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (
      <Formsy onValidSubmit={()=>alert('Valid')} onInvalidSubmit={()=>alert('Invalid')}>
        /* This will Not work! */
        <MyInput required name="test1" title="Test1" validationError="This field is required!" />
        /* This will work! */
        <MyInput required name="test2" title="Test2" validationErrors={{"isDefaultRequiredValue":"This field is required!"}} />
        <button type="submit">Submit to validate!</button>
      </Formsy>
    );
  }
}

ReactDOM.render(<App/>, document.getElementById('example'));

Not sure if it's a bug or my bad implementation but, it's just feels kinda natural to add prop required and if you only have required then validationError is dedicated to required state?

Anyway, thanks for your hard work with Forms!

ekv88 avatar Dec 21 '17 14:12 ekv88

So this is roughly how I have my components built, with required and errors being different things in the render:

const errorMessage = this.props.getErrorMessage()
  , isPristine = this.props.isPristine()
  , isValid = this.props.isValid()
  , showRequired = this.props.showRequired()
  , showError = _.isBoolean(this.props.showError) ? this.props.showError : this.props.showError()
  , showRequiredMessage = !isPristine && !isValid && showRequired;

 {showRequiredMessage &&
   <HelpBlock>{label || 'This field'} is required.</HelpBlock>}

 {showErrorMessage &&
   <HelpBlock>{errorMessage}</HelpBlock>}

Hopefully some other people will chime in, but I would especially check out formsy-react-components by @twisty for examples of great component source.

Does this answer your question? I may have interpreted it incorrectly.

rkuykendall avatar Dec 21 '17 19:12 rkuykendall

It's just my idea to make required easier to use. With just required and validationError without ugly validationErrors={{"isDefaultRequiredValue":"This field is required!"}}.

ekv88 avatar Jan 09 '18 14:01 ekv88

OKAY, two more years working on Formsy and I now understand this issue! The proposal is that when validationError: string and required: true and validations: undefined then validationError should be used as the required error much like it would be used as the validation error.

I think I understand this now, and yes, it does seem to help tighten the usage in that use case. However, on first understanding, it seems very complicated and likely to generate confusion. Does anyone else have any opinions, or want to correct any of my understanding, or advocate for it?

rkuykendall avatar Feb 22 '20 17:02 rkuykendall

hahahahaha, well better ever than never :D This is just something we had problem with, lot of forms with a lot of fields with very long props just to achieve default required state. I've later update this to fallback to isDefaultRequiredValue":"This field is required!" props with just required message and found that kind of approach can hard code required message error, tho that is not that big of a problem.

ekv88 avatar Apr 05 '20 13:04 ekv88