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

Profile - The error message is not triggered right after entering an invalid symbol #23743

Closed
2 of 6 tasks
kbecciv opened this issue Jul 27, 2023 · 13 comments
Closed
2 of 6 tasks
Assignees
Labels
Bug Something is broken. Auto assigns a BugZero manager. Daily KSv2

Comments

@kbecciv
Copy link

kbecciv commented Jul 27, 2023

If you haven’t already, check out our contributing guidelines for onboarding and email contributors@expensify.com to request to join our Slack channel!


Action Performed:

  1. Open the app
  2. Tap the avatar icon
  3. In settings, select Profile > Display name or Legal name
  4. Enter an invalid symbol or word (e.g. semicolon or "Expensify" for Display name) in any of the fields

Expected Result:

The error is displayed as soon as the invalid symbol or word is entered.

Actual Result:

The error is triggered after the user starts entering info in the other field or hits "Save" if the invalid symbol is in the last name field. After emptying fields, the error is shown as soon as the invalid symbol is entered.

Workaround:

Unknown

Platforms:

Which of our officially supported platforms is this issue occurring on?

  • Android / native
  • Android / Chrome
  • iOS / native
  • iOS / Safari
  • MacOS / Chrome / Safari
  • MacOS / Desktop

Version Number: 1.3.46
Reproducible in staging?: y
Reproducible in production?: y
If this was caught during regression testing, add the test name, ID and link from TestRail:
Email or phone of affected tester (no customers):
Logs: https://stackoverflow.com/c/expensify/questions/4856
Notes/Photos/Videos: Any additional supporting documentation

Bug6143469_IMG_0720.mp4

Expensify/Expensify Issue URL:
Issue reported by: Applause - Internal Team
Slack conversation:

@kbecciv kbecciv added Daily KSv2 Bug Something is broken. Auto assigns a BugZero manager. labels Jul 27, 2023
@melvin-bot
Copy link

melvin-bot bot commented Jul 27, 2023

Triggered auto assignment to @alexpensify (Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details.

@melvin-bot
Copy link

melvin-bot bot commented Jul 27, 2023

Bug0 Triage Checklist (Main S/O)

  • This "bug" occurs on a supported platform (ensure Platforms in OP are ✅)
  • This bug is not a duplicate report (check E/App issues and #expensify-bugs)
    • If it is, comment with a link to the original report, close the issue and add any novel details to the original issue instead
  • This bug is reproducible using the reproduction steps in the OP. S/O
    • If the reproduction steps are clear and you're unable to reproduce the bug, check with the reporter and QA first, then close the issue.
    • If the reproduction steps aren't clear and you determine the correct steps, please update the OP.
  • This issue is filled out as thoroughly and clearly as possible
    • Pay special attention to the title, results, platforms where the bug occurs, and if the bug happens on staging/production.
  • I have reviewed and subscribed to the linked Slack conversation to ensure Slack/Github stay in sync

@ygshbht
Copy link
Contributor

ygshbht commented Jul 27, 2023

Proposal

Please re-state the problem that we are trying to solve in this issue.

The app doesn't instantly show an error when invalid input is entered in the Profile fields, but waits until the user interacts with another field or hits "Save".

What is the root cause of that problem?

The form validation currently triggers onBlur or on form submission, not during input changes.

App/src/components/Form.js

Lines 300 to 341 in cd09dc9

onBlur: (event) => {
// We delay the validation in order to prevent Checkbox loss of focus when
// the user are focusing a TextInput and proceeds to toggle a CheckBox in
// web and mobile web platforms.
setTimeout(() => {
setTouchedInput(inputID);
// To prevent server errors from being cleared inadvertently, we only run validation on blur if any form values have changed since the last validation/submit
const shouldValidate = !_.isEqual(inputValues, lastValidatedValues.current);
if (shouldValidate) {
onValidate(inputValues);
}
}, 200);
if (_.isFunction(child.props.onBlur)) {
child.props.onBlur(event);
}
},
onTouched: () => {
setTouchedInput(inputID);
},
onInputChange: (value, key) => {
const inputKey = key || inputID;
setInputValues((prevState) => {
const newState = {
...prevState,
[inputKey]: value,
};
onValidate(newState);
return newState;
});
if (child.props.shouldSaveDraft) {
FormActions.setDraftValues(props.formID, {[inputKey]: value});
}
if (child.props.onValueChange) {
child.props.onValueChange(value, inputKey);
}
},
});
});

What changes do you think we should make in order to solve the problem?

We should adjust the form component to validate the input onChange. This change would involve using a similar approach as the existing onBlur validation but triggered on input changes. Please note that this is a rough solution and the actual implementation may require additional adjustments.

if (props.validateOnInputChange) {
    setTimeout(() => {
        setTouchedInput(inputID);
        const shouldValidate = !_.isEqual(inputValues, lastValidatedValues.current);
        if (shouldValidate) {
            onValidate(inputValues);
        }
    }, 200);
}

@samh-nl
Copy link
Contributor

samh-nl commented Jul 27, 2023

Proposal

Please re-state the problem that we are trying to solve in this issue.

The error message is not triggered right after entering an invalid symbol

What is the root cause of that problem?

Inputs are only validated after they are "touched", which currently happens when blurring the input or submitting the form.
For date pickers, there is an onTouched function, but this is not a valid event for normal inputs.

App/src/components/Form.js

Lines 318 to 320 in cd09dc9

onTouched: () => {
setTouchedInput(inputID);
},

What changes do you think we should make in order to solve the problem?

Inside onInputChange, we should call setTouchedInput(inputID);. We could make this behavior optional via a new Form prop shouldValidateOnChange.

onInputChange: (value, key) => {
	const inputKey = key || inputID;
+	setTouchedInput(inputID);
	setInputValues((prevState) => {
	...

onInputChange: (value, key) => {

What alternative solutions did you explore? (Optional)

Touch the input onFocus, however this may not be desired. Validation makes most sense when an input change occurs.

@hungvu193
Copy link
Contributor

hungvu193 commented Jul 28, 2023

A regression from #23306 where we tried to prevent error was cleared from server when switching tab by comparing the value from lastValidatedValues with currentInputValues, but lastValidatedValues is always updated when we changed the input, which cause the issue. We should revert #23306.
I'm bringing my proposal again from the original issue: #21838

Proposal

Please re-state the problem that we are trying to solve in this issue.

Web - Bank - Error message 'bank account should end with 1111' disappears after switching tab

What is the root cause of that problem?

We always call validate function again when ever input is blurred:

App/src/components/Form.js

Lines 287 to 295 in 5997357

onBlur: (event) => {
// We delay the validation in order to prevent Checkbox loss of focus when
// the user are focusing a TextInput and proceeds to toggle a CheckBox in
// web and mobile web platforms.
setTimeout(() => {
setTouchedInput(inputID);
onValidate(inputValues);
}, 200);

Let take a look at our onValidate function, as we can see it always clear the server error which caused this issue:
FormActions.setErrors(props.formID, null);

What changes do you think we should make in order to solve the problem?

That make senses to clear server errors when input changed but when input is blurred we should keep the server errors.
So we will need to create a new variable called hasServerErrors:

const hasServerError = useMemo(() => Boolean(props.formState) && !_.isEmpty(props.formState.errors), [props.formState]);

Also update our onValidate function with a new param called shouldClearServerError default value is true and we only clear server errors when shouldClearServerError equals true.

    const onValidate = useCallback(
        (values, shouldClearServerError = true) => {
      // other codes
            if (shouldClearServerError) {
                FormActions.setErrors(props.formID, null);
            } 

Finally update our onBlur function (don't forget to add hasServerError in the dependencies list)

                    onBlur: (event) => {
                        // We delay the validation in order to prevent Checkbox loss of focus when
                        // the user are focusing a TextInput and proceeds to toggle a CheckBox in
                        // web and mobile web platforms.
                        setTimeout(() => {
                            setTouchedInput(inputID);
                            onValidate(inputValues, !hasServerError);
                        }, 200);

What alternative solutions did you explore? (Optional)

If we can synchronize the validation of account number between client and server then we can avoid this issue.

Result:

Screen.Recording.2023-06-29.at.07.18.43.mov

@joh42
Copy link
Contributor

joh42 commented Jul 28, 2023

Working on a fix for this regression from issue #21838

@joh42
Copy link
Contributor

joh42 commented Jul 28, 2023

FYI a PR to fix this regression is awaiting review @alexpensify

@alexpensify
Copy link
Contributor

I ran out of time yesterday and am OOO today. I'll try to review it over the weekend.

@joh42
Copy link
Contributor

joh42 commented Jul 29, 2023 via email

@melvin-bot melvin-bot bot added the Overdue label Jul 31, 2023
@alexpensify
Copy link
Contributor

Sorry @joh42 - I missed your comment. Please keep me posted if this bug is still around after the fix is live.

@melvin-bot melvin-bot bot removed the Overdue label Jul 31, 2023
@alexpensify
Copy link
Contributor

@joh42 - it looks like the PR went to staging yesterday, can you confirm if we can close this one out? Thanks!

@joh42
Copy link
Contributor

joh42 commented Aug 2, 2023

Thanks for the ping, this can be closed now @alexpensify

Screen.Recording.2023-08-02.at.19.40.50.mov

@alexpensify
Copy link
Contributor

Perfect, thank you for that update!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Something is broken. Auto assigns a BugZero manager. Daily KSv2
Projects
None yet
Development

No branches or pull requests

6 participants