Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FIO-9072: required validation triggered on form load #5846

Conversation

ZenMasterJacob20011
Copy link
Contributor

Link to Jira Ticket

https://formio.atlassian.net/browse/FIO-9072

Description

Webform.js

  • Added explicit submission to flags so that it can be used to make a component dirty or not
  • Made it so that if noValidate flag is set to true then the component will not validate. This was a problem because sometimes the noValidate flag was set to undefined causing shouldNotValidate to be true unexpectedly

Component.js

  • Changed it so that when the dirty flag is set to true it doesn't propagate to sibling components
  • Changed it so that the components dirty property is set to true when there is an explicit submission

NestedComponent.js

  • Component now uses a copy of flags so that a change in flags from one component does not propagate throughout other components

Editgrid.js

  • If the Editgrid is dirty then the row should be validated

Why have you chosen this solution?

This solution is probably the closest to what the best solution would be. Unfortunately it is not a small change to make it so that the required validation is not triggered on form init. There is a lot of assumptions made around the dirty flag and it seems as though we were just getting lucky that this hasn't appeared before. A lot of the changes made here fix these assumptions.

Breaking Changes / Backwards Compatibility

N/A

Dependencies

N/A

How has this PR been tested?

Added automated tests and manually tested. Also changed some tests which I will discuss in dev support

Checklist:

  • I have completed the above PR template
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation (if applicable)
  • My changes generate no new warnings
  • My changes include tests that prove my fix is effective (or that my feature works as intended)
  • New and existing unit/integration tests pass locally with my changes
  • Any dependent changes have corresponding PRs that are listed above

@TanyaGashtold
Copy link
Contributor

The changes seem logical to me. But I feel like they're a little risky. I want someone else to review them.

if (flags.fromSubmission && this.hasValue(data)) {
flags.dirty = this.pristine && this.component.protected ? false : true;
if (flags.fromSubmission && !_.isUndefined(_.get(flags?.submission?.data, this.key)) && !(this.pristine && this.protected)) {
dirty = this.pristine && this.component.protected ? false : true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems to me that this.protected is always undefined. I was not able to find a place where it is set to true/false.
Why do we need the check for 'protected' and 'pristine' in both line 3395 and line 3394?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure. It looks like I accidentally added this when trying to resolve merge conflicts. I will remove it

@@ -795,6 +795,7 @@ export default class Webform extends NestedDataComponent {
*/
onSetSubmission(submission, flags = {}) {
this.submissionSet = true;
flags.submission = structuredClone(submission);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this necessary? I don't like the idea of creating a clone of the submission object here so it can be passed along to the setValue method. Is this absolutely necessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is so that the explicit submission can be used to determine whether or not to show validation. I could not use this.data or this.submission because these are filled with this.empty value. e.g. button components get false, textfield components get and empty string. I need to know the exact submission at the time it was inputted to determine if it was given an empty value or if it was not even a property in the submission json.

}
if (flags.fromSubmission && this.hasValue(data)) {
flags.dirty = this.pristine && this.component.protected ? false : true;
if (flags.fromSubmission && !_.isUndefined(_.get(flags?.submission?.data, this.key)) && !(this.pristine && this.protected)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_.get(submission.data, this.key) not always the way to fetch the correct data for a component. Particularly the Checkbox components configured as Radio components would fail here. Why can we not use "this.hasValue"? It looks like you can pass data to it... maybe change this to this.hasValue(flags?.submission.data)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hasValue(data) {
return !.isUndefined(.get(data || this.data, this.key));
}
hasValue will fallback on this.data. I do not want it to fall back on this.data because I want the explicit submission to set if the dirty flag is true. this.data will be populated with this.empty values in the init function of setting up the form. I need absolutely sure that the property was set by whoever defined the submission object in setSubmission(...). This is why I added the submission to the flags object when a submission is set.

@@ -927,22 +927,24 @@ export default class NestedComponent extends Field {

setNestedValue(component, value, flags = {}) {
component._data = this.componentContext(component);
let componentFlags = {...flags};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this necessary anymore now that we are no longer mutating the "dirty" property? I would prefer to not have to clone if we don't need to.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants