Skip to content

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

Closed

Description

@kbecciv

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:

Activity

  1. added
    BugSomething is broken. Auto assigns a BugZero manager.
    on Jul 27, 2023
  2. melvin-bot commented on Jul 27, 2023

    @melvin-bot

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

  3. melvin-bot commented on Jul 27, 2023

    @melvin-bot

    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
  4. ygshbht commented on Jul 27, 2023

    @ygshbht
    Contributor

    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);
    }
    
    
  5. samh-nl commented on Jul 27, 2023

    @samh-nl
    Contributor

    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.

  6. hungvu193 commented on Jul 28, 2023

    @hungvu193
    Contributor

    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
  7. joh42 commented on Jul 28, 2023

    @joh42
    Contributor

    Working on a fix for this regression from issue #21838

  8. joh42 commented on Jul 28, 2023

    @joh42
    Contributor

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

  9. alexpensify commented on Jul 28, 2023

    @alexpensify
    Contributor

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

  10. joh42 commented on Jul 29, 2023

    @joh42
    Contributor
  11. alexpensify commented on Jul 31, 2023

    @alexpensify
    Contributor

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

  12. alexpensify commented on Aug 2, 2023

    @alexpensify
    Contributor

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

  13. joh42 commented on Aug 2, 2023

    @joh42
    Contributor

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

    Screen.Recording.2023-08-02.at.19.40.50.mov
  14. alexpensify commented on Aug 2, 2023

    @alexpensify
    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

Metadata

Metadata

Assignees

Labels

BugSomething is broken. Auto assigns a BugZero manager.DailyKSv2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions