react-redux-form icon indicating copy to clipboard operation
react-redux-form copied to clipboard

Validity(Errors) set as array doesn't get cleared when the field is modified

Open ignatiusreza opened this issue 7 years ago • 10 comments

The Problem

This is a followup on #834 (thanks for fixing the bug!), which would now correctly keep the error message set via actions.setFieldsError.. the problem is now, editing the field does not reset the field validity.. which broke the form and make it impossible to be submitted..

I'm not entirely sure if this is the right approach to process server side validation to be honest.. if it is not, what would be the suggested way?

Steps to Reproduce

  1. create a form
  2. make it valid from the point of view of client side validation
  3. onSubmit, call actions.setFieldsError to set the fields errors, simulating errors due to server side validation
  4. edit any field

Expected Behavior

errors set via actions.setFieldsError should be reset when the field is edited

Actual Behavior

errors set via actions.setFieldsError stick around, making the form forever invalid

Reproducible Code Example

(CodePen)

ignatiusreza avatar Jun 26 '17 10:06 ignatiusreza

Hmm, this is more something that hasn't exactly been considered. Here's a potential way to fix this as an added feature:

// future API!
dispatch(actions.setFieldsErrors('user.something', {
  foo: true,
  bar: true
}, { transient: true }); // << this is new

These will "mark" the validator keys 'foo' and 'bar' internally as transient, which means that they will disappear once the control changes, similar to how async validators work.

How does this sound?

davidkpiano avatar Jun 26 '17 16:06 davidkpiano

Sorry, haven't played around with async validation much to understand the comparison.. but, it sounds like it could solve the use case, as long as it doesn't clear up the errors on page navigation (remount)...

ignatiusreza avatar Jun 26 '17 18:06 ignatiusreza

as long as it doesn't clear up the errors on page navigation (remount)...

Right, it would only clear transient errors when an actions.change action for that model is dispatched.

davidkpiano avatar Jun 26 '17 18:06 davidkpiano

Took a quick look into async validation.. and it got me thinking that maybe the timing of when the errors should be cleared should be controlled by either validateOn or asyncValidateOn.. as of now, I'm leaning more toward asyncValidateOn (on blur).. but, this is more because so far, I have only found the need to explicitly use actions.setFieldsError when handling async validation on form submit.. everything else can be handled via validators or errors props.. wdyt?

ignatiusreza avatar Jun 27 '17 01:06 ignatiusreza

Managed to work around this issue by normalizing the errors to something like

dispatch(actions.setFieldsErrors('user.something', {
  foo: { async: 'foo is not bar' },
  bar: { async: 'bar is not foo' },
});

and then to have the following on each Control:

<Form model="user.something">
  <Control.text model="foo" asyncValidators={{ async: (_, done) => done(true) }} />
  <Control.text model="bar" asyncValidators={{ async: (_, done) => done(true) }} />
</Form>

a bit cumbersome to do, but it's working :grin:

ignatiusreza avatar Jul 03 '17 10:07 ignatiusreza

Hi,

I have the same issue. I am expecting the same behaviour as setErrors.

setErrors action behaviour:

  1. I send the form
  2. The backend responded with an error
  3. I dispatch the action setErrors with the errors
  4. The message is shown in the form.
  5. I edit a field and the form becomes valid again, so is possible to re-submit (excellent)

setFieldsErrors action behaviour:

  1. I send the form
  2. The backend responded with an error
  3. I dispatch the action setFieldsErrors with the errors
  4. The message is shown in the fields that have errors
  5. I edit the fields that have errors, and the form never become valid again, so is not possible to re-submit

I have tried the piece of advice that you has mentioned using { transient: true } but didn't work.

regards,

Marcos.

marcosschroh avatar Jul 29 '17 02:07 marcosschroh

I have tried the piece of advice that you has mentioned using { transient: true } but didn't work.

That's coming up in a future version.

davidkpiano avatar Jul 29 '17 13:07 davidkpiano

Has anyone made any progress on this front?

As a workaround, I'm currently using this on my mapProps:

onChange: (props : any) => () => props.dispatch(actions.resetValidity(props.model))

fabiob avatar Sep 28 '17 00:09 fabiob

Is there any progress on the transient parameter on the setFieldsErrors action? Is it also going to be propagated to actions that use setFieldsErrors like submitFields?

jjmr avatar Jan 29 '18 09:01 jjmr

Sorry @jjmr I've been extremely busy - if you know how transient can be implemented (should be straightforward) I'd be glad to review and accept such a PR as soon as possible.

davidkpiano avatar Jan 29 '18 13:01 davidkpiano