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: Request to expose functionality to code such as .reset() , .validate(), .submit(), etc #7046

Closed
4 tasks
BenJackGill opened this issue Jan 6, 2025 · 5 comments
Assignees
Labels
Type: Enhancement Issue contains an enhancement related to a specific component. Additional functionality has been add
Milestone

Comments

@BenJackGill
Copy link

Describe the bug

Description

Currently, the Form component only exposes form state via the v-slot="$form", making it difficult to programmatically control forms from script code. Common operations like resetting, validating, or submitting forms require direct template access to $form, which creates unnecessary coupling between template and logic.

Related Issues and Discussions

This functionality has been requested in various forms across different issues. I'm creating this consolidated issue to track the core problem: the need for programmatic form control. Related issues and discussions:

While these issues approach the problem from different angles, they all stem from the same root cause: lack of programmatic access to form methods. Having a single solution that exposes a complete form instance API would resolve all these cases.

We need the ability to call form methods from script code for scenarios like:

  • Resetting form after API operations
  • Programmatic validation before custom operations
  • Triggering form submission from parent components
  • Setting form values after async operations (e.g., fetching data from APIs)
  • Handling complex form state management in composables

Example Use Case

<template>
  <Form ref="formRef">
    <InputText name="username" />
    <Button @click="handleExternalAction">External Action</Button>
  </Form>
</template>

<script setup lang="ts">
import { Form } from '@primevue/forms';
import { useTemplateRef } from 'vue';

const formRef = useTemplateRef('formRef');

const handleExternalAction = async () => {
  // Currently impossible - need to access form methods programmatically
  if (await formRef.value?.validate()) {
    const response = await api.getData();
    formRef.value?.setValues({
      username: response.username,
    });
  }
};
</script>

Proposed Solution

This is just a suggestion:

interface FormInstance {
  // Reset form to initial values
  reset(): void;
  
  // Validate form (returns same shape as current validation)
  validate(): Promise<{
    valid: boolean;
    errors: any[];
  }>;
  
  // Set values (matches initialValues prop type)
  setValues(values: Record<string, any>): void;
  
  // Submit form (returns same shape as FormSubmitEvent)
  submit(): Promise<{
    originalEvent: Event;
    values: Record<string, any>;
    states: Record<string, FormFieldState>;
    valid: boolean;
    errors: any[];
  }>;
}

Benefits

  • Better programmatic control of forms
  • Easier integration with async operations
  • More consistent with other form libraries like React Hook Form

Pull Request Link

No response

Reason for not contributing a PR

  • Lack of time
  • Unsure how to implement the fix/feature
  • Difficulty understanding the codebase
  • Other

Other Reason

No response

Reproducer

N/A

Environment

Node

Vue version

3.5.13

PrimeVue version

4.2.5

Node version

No response

Browser(s)

No response

Steps to reproduce the behavior

See above

Expected behavior

See above

@BenJackGill BenJackGill added the Status: Needs Triage Issue will be reviewed by Core Team and a relevant label will be added as soon as possible label Jan 6, 2025
@mertsincan mertsincan added this to the 4.3.0 milestone Jan 6, 2025
@github-project-automation github-project-automation bot moved this to Review in PrimeVue Jan 6, 2025
@mertsincan mertsincan added Status: Pending Review Issue or pull request is being reviewed by Core Team and removed Status: Needs Triage Issue will be reviewed by Core Team and a relevant label will be added as soon as possible labels Jan 6, 2025
@mertsincan mertsincan self-assigned this Jan 6, 2025
@mertsincan mertsincan added Type: Enhancement Issue contains an enhancement related to a specific component. Additional functionality has been add and removed Status: Pending Review Issue or pull request is being reviewed by Core Team labels Jan 8, 2025
@github-project-automation github-project-automation bot moved this from Review to Done in PrimeVue Jan 8, 2025
@mertsincan
Copy link
Member

Exp;

import { Form, type FormInstance } from '@primevue/forms';

const formRef = useTemplateRef<FormInstance>('formRef');

@goldengecko
Copy link

It would also be nice to be able to handle async validations that happen during submission nicely - something like the vee-validate isSubmitting so we can show a spinner while it does some async work in the background to validate.

Also the current mechanism seems to make it difficult to do things like initially validate on blur, but if there is an error, validate on change so the user can know when they have fixed the problem.

@xak2000
Copy link

xak2000 commented Feb 7, 2025

Also the current mechanism seems to make it difficult to do things like initially validate on blur, but if there is an error, validate on change so the user can know when they have fixed the problem.

I agree that this is more user friendly way to validate forms.
Most form on Google's sites works this way too (e.g. Google Cloud Console forms).

I solved this problem temporarily like this. I hope there will be a better solution in the future version:

// Validate on blur until field is touched, then validate on each update (eagerly)
const form = useTemplateRef<{ states: Record<string, FormFieldState | undefined> }>('form')
const validateOnValueUpdate = computed(() => {
  const states = form.value?.states ?? {}
  return Object.keys(states).filter((field) => states[field]?.touched ?? false)
})
<Form ref="form" :validate-on-value-update :validate-on-blur="true">...</Form>

So, it is not difficult. The only tricky part is to access internal API of the form instance, that I would like to avoid.

But of course it would be much better to have this option out of the box, e.g. be able to set validate-on-value-update="touched".

@BenJackGill
Copy link
Author

BenJackGill commented Feb 26, 2025

But of course it would be much better to have this option out of the box, e.g. be able to set validate-on-value-update="touched".

Did anything like this get added with the new 4.3.0 update?

Specifically, validation should not trigger while typing but should validate on blur. If an error appears, it should then validate on input so the error clears immediately while typing. This prevents premature validation distractions while typing and ensures errors resolve smoothly, improving the user experience.

Previously I was using VeeValidate like that and it provided the best user experience.

@xak2000
Copy link

xak2000 commented Feb 27, 2025

Specifically, validation should not trigger while typing but should validate on blur. If an error appears, it should then validate on input so the error clears immediately while typing.

I somewhat disagree with this logic. Or, rather, I almost agree, but with one change.

I think the better would be like this:

Validation should not trigger while typing but should validate on blur. If validation of this field is performed at least once (so, the field's touched state is true now), it should then validate on input so the error (if any) clears immediately while typing, but also the error appears immediately while typing (so, if user returns to the valid field and changes the valid value to an invalid value).

So, the change in the logic I suggest is to switch to "eager validation" not only on error, but also when there was no error, but user touched the field. This way the validation will not be premature, but at the same time if user toches the field again and changes the value from a valid to an invalid, the user will immideately see the feedback.

I seen exactly this logic in many well-known admin panels of big companies and I think this is the most user-friendly way in most cases.

Did anything like this get added with the new 4.3.0 update?

Answering this question: I don't think so. It was just an idea that most likely left unseen by someone who really could take this decision. Maybe it is worth to open a new issue for this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type: Enhancement Issue contains an enhancement related to a specific component. Additional functionality has been add
Projects
Status: Done
Development

No branches or pull requests

4 participants