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

fix: revalidateField does not trigger promise validation directly #112

Open
kokoal opened this issue Feb 17, 2023 · 1 comment
Open

fix: revalidateField does not trigger promise validation directly #112

kokoal opened this issue Feb 17, 2023 · 1 comment

Comments

@kokoal
Copy link

kokoal commented Feb 17, 2023

In some cases we want to validate a particular form field on an user action first without validating all form fields. And do final validation on fomr submit.

As for an exemple you have a promo code field you want to validate when the user click on a "Apply" button this will trigger a fetch (with Promise) validator and only validate the field containing the promo code.

In this case I try using revalidateField but it seems to not run the promise and always return true.

My full example :

applyPromoCodeButton.addEventListener('click', clickApplyButton);

let promotionalCodeError = '';
const getPromotionalCodeError = () => {
  return promotionalCodeError;
}

validation.addField(promotionalCodeField, [
  {
    validator: (code) => () => {
      return new Promise((resolve) => {
        if (code.length <= 0) {
          resolve(true);
          return;
        }
        const validatePromotionalCodeReadyUrl = validatePromotionalCodeUrl
          .replace('{code}', code)
          .replace('{orderNumber}', orderNumber);
        fetch(validatePromotionalCodeReadyUrl)
          .then(response => {
            return response.json();
          })
          .then(validation => {
              if (validation.valid === false) {
                promotionalCodeError = validation.reason;
              }
              resolve(validation.valid);
          });
      });
    },
    errorMessage: getPromotionalCodeError,
  }
]);

function clickApplyButton(event) {
  // Deactivate form submission.
  event.preventDefault();
  // Manually trigger promotional code field validation.
  validation.revalidateField(promotionalCodeField).then(isValid => {
    // Do something more, eventually.
  });
}

The only workaround I found is to use directly validateField with afterInputChanged at false.
Like so :

validation.validateField(key, false).finally(() => {
  validation.clearFieldStyle(key);
  validation.clearFieldLabel(key);
  validation.renderFieldError(key, true);
});

Do I did something wrong, or is that wanted from revalidateField ?

@hmsun-es
Copy link

I think that the revalidateField method should perform all validation unconditionally because it is checked at a specific point the developer wants.
In my case, I want to perform asynchronous validation when focusing out of a specific tag, but I have a validation problem with the same problem.
The correct code I think is:

  revalidateField(fieldSelector) {
    if (typeof fieldSelector !== "string" && !isElement(fieldSelector)) {
      throw Error(
        `Field selector is not valid. Please specify a string selector or a valid DOM element.`
      );
    }
    const key = this.getKeyByFieldSelector(fieldSelector);
    if (!key || !this.fields[key]) {
      console.error(`Field not found. Check the field selector.`);
      return Promise.reject();
    }
    return new Promise((resolve) => {
      // AS-IS
      // this.validateField(key, true).finally(() => {
      // TO-BE
      this.validateField(key, false).finally(() => {
        this.clearFieldStyle(key);
        this.clearFieldLabel(key);
        this.renderFieldError(key, true);
        resolve(!!this.fields[key].isValid);
      });
    });
  }

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

No branches or pull requests

2 participants