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

Form component - Backend validation #474

Closed
menthol opened this issue Aug 1, 2023 — with Volta.net · 5 comments · Fixed by #487
Closed

Form component - Backend validation #474

menthol opened this issue Aug 1, 2023 — with Volta.net · 5 comments · Fixed by #487

Comments

Copy link

menthol commented Aug 1, 2023

Good work on the form component.

I've tested it, but it's hard to use with a Laravel Precognition-type backend or normal backend validation.

I suggest two improvements:

  • the validation should be called with a second parameter, the name of the field that triggered the validation (validate(state, trigger)), so that we can validate only the field that the user actually touched.
  • Secondly, we should be able to give the list of error list directly in props. Some checks can only be made once the form has been submitted. It might be useful to be able to display errors afterwards.
@romhml
Copy link
Collaborator

romhml commented Aug 1, 2023

Thanks! I'll look into adding support for back-end validation / handling errors after submission. Do you have a small example I can play with to test the integration with Laravel Precognition?

@menthol
Copy link
Author

menthol commented Aug 1, 2023

Maybe somthing like this very dirty example:

let errors = [];
let response = ref<Todo|null>(null);
async function validate(state, trigger) {
    if (! trigger) {
        try {
            errors = [];
            response.value = await $fetch(
                '/api/todo',
                {
                    method: 'POST',
                    body: state.value
                })
        } catch (e) {
            response.value = null;

            if (e.response.status === 422) {
                errors = e.response.data.errors.map((errors, path) => ({
                    path,
                    message: errors[0],
                }));
            }
        }
        
        return errors;
    }
    
    try {
        errors = errors
            .filter(error => error.path !== trigger);

       response = await $fetch(
            '/api/todo',
            {
                method: 'POST',
                body: {
                    [trigger]: state.value[trigger]
                },
                headers: {
                    'Precognition': 'true',
                    'Precognition-Validate-Only': trigger,
                }
            })
    } catch (e) {
        if (e.response.status === 422 && e.response.data?.errors?.[trigger]) {
            errors.push({
                path: trigger,
                message: e.response.data.errors[trigger][0],
            });
        }
    }
    
    return errors;
}

@romhml
Copy link
Collaborator

romhml commented Aug 1, 2023

Can you try something like this?

<script setup lang="ts">
import { useForm } from "laravel-precognition-vue";

const formRef = ref();
const f = useForm("post", "/users", {
  name: "",
  email: "",
});

async function validateWithPrecognition() {
  f.touch();
  await f.validate();
  return v.errors().entries().map((error) => ({
    message: error[1],
    path: error[0],
  }));
}

defineExpose({
  validate: async () => {
    await form.value.validate();
  },
});
</script>

<template>
  <UForm
    ref="formRef"
    :model="form.data()"
    :validate="validateWithPrecognition"
  >
    <slot />
  </UForm>
</template>

I checked this: https://github.com/laravel/precognition/blob/main/packages/vue/src/index.ts#L108
It looks like you can trigger validation without directly calling your endpoint

@menthol
Copy link
Author

menthol commented Aug 1, 2023

No you can't,
The precognition is a backend part of Laravel partial validation mecanism.
The Laravel packages are used to be implemented directly in vue and use axios for handling requests.
So I always self implements the Vue/Js part of Precognition.

The example you provide use frontend validation and not the precognition one.

@menthol
Copy link
Author

menthol commented Aug 1, 2023

I think per field validation and backend validations are two subject that require individual request

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 a pull request may close this issue.

2 participants