ealush / vest

Vest ✅ Declarative validations framework

Home Page:https://vestjs.dev/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to initialise (pre-populate) form?

enyo opened this issue · comments

(I'm using Svelte + Svelte Kit but that shouldn't matter to this question)

I create my suite in a separate file, and have my component setup something like this:

  let result = suite.get()
  let formData: FormData = {
    projectName: '',
    redirectUrl: '',
    allowedOrigins: '',
  }

Everything works fine, however I can't submit my form, because result.isValid() is not true (thus disabling my submit button), because some tests have been skipped. That's understandable, because if I don't edit every field, then their tests will be skipped.

How can initialise my form in a way that the tests are marked as valid and it allows me to submit the form without immediately displaying all errors?

Hey @enyo 👋
Just to clarify, are the values filled to begin with?
If so, then just call the suite without providing any field name to only, it will just run the suite as a whole and not skip any field.

Alternatively, do you want to submit the form when all the fields can be blank? If so, you can mark them as optional so they can be omitted from the run and still be counted as valid.

Lastly, are you using V3 or the vest@next build? I'm asking because the next version brings some improvements regarding optional fields.

I hope that helps

Hi @ealush thanks for your reply.

I'm interested in the former example. Let's say, I have a "Finish registration" page, and I already know the name (because it was in the verification email) but I still allow the user to enter it.

So my initial form data would be:

{
  name: 'Already provided',
  password: '',
}

If I now pass this to vest, it'll fail validation for password and show an error before the user started entering something.
But if I don't do it, then the user will need to modify the name field once so it passes validation.

I guess a solution (that I just came up with) is to provide only: ['name'] in the initialisation. That would work for me. Is that also your recommendation?

I see. This requirement makes perfect sense. The main issue I see is that Vest cannot by itself be aware of your internal business logic, and it cannot know whether to omit certain fields or not.

An alternative solution to yours would be optionally calling optional with name, assuming that you know for a fact that name has actually been filled. This will remove the need for forcing an initial run prior to user interaction.

something like this might work:

import {create, test, enforce, only, optional} from 'vest';

const suite = create((data = {}, {currentField, preFilled}) => {
	if (preFilled) optional('name');
	only(currentField)

	test("name", "Name is required", () => {
		enforce(data.name).isNotBlank();
	});

	test("password", "Name is required", () => {
		enforce(data.password).isNotBlank();
	});
});

The next version of Vest will introduce some improvements in this space, with advanced functional optional fields, but I think for your case, my example above is sufficient.

Let me know if either of these works for you.

Ah yes that looks like the perfect solution. Thanks!