christianalfoni / formsy-react

A form input builder and validator for React JS
MIT License
2.6k stars 436 forks source link

Ajax validation rule. #261

Open minvs1 opened 8 years ago

minvs1 commented 8 years ago

I want to add validation rule to check if value is unique in database. So basically I just post request to back-end and wait till i get response if value is unique or not. Also I use underscore.js's debounce function to reduce calls to server. But input is being invalidated before ajax callback comes.

Code looks something like this:

Formsy.addValidationRule 'isUnique', (values, value)->
  return checkUnique(values, value)

checkUnique = _.debounce((values, value)=>
  unique = false

  request = $.ajax url: '/uniqueness-check', method: 'POST', data: {field: 'PaymentGateway.name', value: value}, async: false, dataType: 'json'

  request.done (response)->
    if response.status
      unique = true

  request.always ->
    console.log 'callback'

  return unique
, 300)

I tried many different version, but nothing seems to work. I also tried to validate input in Input component. I just accessed validations props and checked if it had isUnique parameter and validated it - errors = uniqueCheckErrors || this.getErrorMessage()., but I could figured out how to add error to Formsy error stack(so I could get them through this.getErrorMessage()) so form would act as normal.

minvs1 commented 8 years ago

The perfect solution I think would allow to invalidate input like this:

Formsy.addValidationRule 'isUnique', (inputRef, values, value)->
  return checkUnique(inputRef, values, value)

checkUnique = _.debounce((inputRef, values, value)=>
  unique = false

  request = $.ajax url: '/uniqueness-check', method: 'POST', data: {field: 'PaymentGateway.name', value: value}, dataType: 'json'

  request.done (response)->
    if response.status
      unique = true

  unless unique
    inputRef.invalidate()
, 300)
kelly-kellerheikkila commented 8 years ago

+1

It would be great to arbitrarily declare an input as invalid.

jcrjaci commented 7 years ago

For anyone who need to validate some field with an AJAX request here are an work around example:

this.validateName = _.debounce(this.validateName.bind(this), 500);

validateName(field, value) {
    const state = {};

    $.when(this.serverValidation(value)).then((validation) => {
        state.nameIsValid = validation;
    }).catch((validation) => {
        state.nameIsValid = validation;
    })
    .done(() => {
        state.name = value;
        this.setState(state);
    });
}

serverValidation(name) {
// make your server request and resolve the validation
}

<MyInput
    name={this.state.name}
    onChange={this.validateName}
    validations={{
        nameIsValid: () => this.state.nameIsValid,
    }}
>
yantakus commented 6 years ago

@jcrjaci When I try using your solution, I get the following error: Formsy does not allow you to override default validations. It seems this way of doing validation was deprecated: https://github.com/christianalfoni/formsy-react/blob/f7cf41dc2eaf06500e0f7f04445c137af13a70ec/src/main.js#L311-L313 If you pass a function as validator it throws an error.

Is there another way of doing this?