nuxt / ui

A UI Library for Modern Web Apps, powered by Vue & Tailwind CSS.
https://ui.nuxt.com
MIT License
3.86k stars 478 forks source link

form validate api throws an error and prevents @error event. #1597

Open jimbatamang opened 6 months ago

jimbatamang commented 6 months ago

Environment


Version

v2.13.0

Reproduction

https://stackblitz.com/edit/nuxt-ui-u1sg9t?file=app.vue

Description

While using validate() api, it throws the following error and won't fire the @error event on form.

Form.vue:98 Uncaught (in promise) Error: Form validation failed: [

Expected:

Validate the form, if there is an error should able to listen the error event on form so that I can emit the error to parent component.

Or form.value.validate should return the errors while calling from defineExpose.

Additional context

I'm using the form inside the ` and need to validate the form when user click/switch to different tab. For this, I am validating the form programatically.

Logs

Form.vue:98 Uncaught (in promise) Error: Form validation failed: [
  {
    "path": "project",
    "message": "Please provide project name."
  }
]
    at Proxy.validate (Form.vue:98:15)
    at async Proxy.validate (form.vue:20:5)
YIngChenIt commented 6 months ago

You can use try...catch... to manually catch errors and solve your problem.

async function validateInsideForm() {
  try {
    await form.value.validate();
  } catch (error) {
    emits('error', error);
  }
}
jimbatamang commented 6 months ago

You can use try...catch... to manually catch errors and solve your problem.

async function validateInsideForm() {
  try {
    await form.value.validate();
  } catch (error) {
    emits('error', error);
  }
}

Thank you so much for your reply. I think partially yes, try catch will help me to resolve my issue in a patchy way only.

The error is coming as a string. That means, I will have to find the [] part either using regex or replacing and parsing them in to array.

YIngChenIt commented 6 months ago

您可以使用 try...catch... 手動捕獲錯誤並解決您的問題。

async function validateInsideForm() {
  try {
    await form.value.validate();
  } catch (error) {
    emits('error', error);
  }
}

非常感謝你的回覆。我認為部分是的,嘗試捕獲只會幫助我以零散的方式解決我的問題。

錯誤以字串形式出現。這意味著,我必須[]使用正規表示式或將它們替換並解析為數組來找到該部分。

You are right.

@benjamincanac

Is it necessary for us to trigger emit('error', error) when calling validate, and throw error information in array format, just like validation during submission?

jimbatamang commented 6 months ago

您可以使用 try...catch... 手動捕獲錯誤並解決您的問題。

async function validateInsideForm() {
  try {
    await form.value.validate();
  } catch (error) {
    emits('error', error);
  }
}

非常感謝你的回覆。我認為部分是的,嘗試捕獲只會幫助我以零散的方式解決我的問題。 錯誤以字串形式出現。這意味著,我必須[]使用正規表示式或將它們替換並解析為數組來找到該部分。

You are right.

@benjamincanac

Is it necessary for us to trigger emit('error', error) when calling validate, and throw error information in array format, just like validation during submission?

I think to make this validate api call usable and unify with other error standards, yes it should return the simple array/object format.

for now, I'm doing this unnecessary steps to resolve this issue (temporary solution)

try {
        await form.value.validate()
    } catch (error) {
        const errorString = error.toString()
        const trimmedErrorString = errorString.replace(/Error: Form validation failed: /, '');
        const errorObject = JSON.parse(trimmedErrorString);

        onError(errorObject)
        return
    }
romhml commented 5 months ago

Errors are also exposed through the form's api so you can simplify your example with something like this:

try {
  await form.value.validate()
} catch (error) {
  onError(form.value.getErrors())
  return
}

I'll look into including the error array directly into the FormException for simplification.

Is it necessary for us to trigger emit('error', error) when calling validate, and throw error information in array format, just like validation during submission?

I think the default behavior should stay the same for use cases like this:

function submit() {
  const state = await form.value.validate()
  post('/todo', state) // Will only post if the state is valid 
}

What we can do is to add an option to the validate function to emit instead of throwing an error, like this:

function submit() {
  const state = await form.value.validate({ emit: true })
}
jimbatamang commented 5 months ago
onError(form.value.getErrors())

Thanks @romhml for your reply.

I like the idea of getting the errors from form's api.

The reason, I was expecting the error responses on validate was because I'm validating the form by parent component and need to know the errors if it fails.

The proposed solution state = await form.value.validate({ emit: true }) seems to be a simple and cleanest solution.

romhml commented 5 months ago

After discussing it with @benjamincanac, we'll add the option in the next major version.