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

Make it possible to remove a validator from a field #2698

Open
peholmst opened this issue Sep 3, 2024 · 7 comments
Open

Make it possible to remove a validator from a field #2698

peholmst opened this issue Sep 3, 2024 · 7 comments
Labels
enhancement New feature or request hilla Issues related to Hilla needs design

Comments

@peholmst
Copy link
Member

peholmst commented Sep 3, 2024

Describe your motivation

You can currently add validators to a field using useFormPart. This assumes that a form remains static once created. Dynamic forms, where fields and validators are added and removed according to the current state of the form, are difficult or even impossible to build easily. Example: if you fill in a street address, the city and zip code fields also become required, otherwise they are optional.

Describe the solution you'd like

An API for disabling/enabling or removing a validator that has already been added, something like this:

const myField = useFormPart(form.model.myField)
const validatorHandle = myField.addValidator(new NotEmpty({message: "Please enter a value"}))
...
validatorHandle.remove()

If a validator that impliesRequired is removed (or disabled), and there are no other validators that also imply required, the field's required property should be reset to false.

Describe alternatives you've considered

Creating a custom validator for all conditional fields that always returns true when the validator is "disabled" and otherwise delegates to the real validator. This would work with validation, but not with impliesRequired.

Additional context

I'm open to other suggestions.

@peholmst peholmst added enhancement New feature or request hilla Issues related to Hilla labels Sep 3, 2024
@Legioth
Copy link
Member

Legioth commented Sep 3, 2024

A variable like validatorHandle is not practical with React since you would then have to store the value as an explicit state variable to keep it preserved between invocations of the render method.

It might be more aligned with the React philosophy that you re-add the validator every time the component is rendered and "remove" the validator by not re-adding it.

@peholmst
Copy link
Member Author

peholmst commented Sep 3, 2024

That's a good point, I didn't think about that. Re-adding the validator every time the component renders does sound more reactish, at least to my n00b ears. At the same time it feels a bit strange. There has to be a better way of solving this problem.

@Legioth
Copy link
Member

Legioth commented Sep 3, 2024

Actually now when I think about it a bit deeper, what you have written there looks like a memory leak if you keep adding a new validator every time the render function is run. I wonder how this API is even supposed to be used in the happy path case?

@cromoteca
Copy link
Contributor

No matter which validation you want to use, you need to implement that server-side first. I think that having most of the validation automatically replicated on the client is already great. You can delegate the full validation to the server and invoke it on each focus event, for example. And for the required indicators, you can still use required={expression} in React.

@peholmst
Copy link
Member Author

peholmst commented Sep 3, 2024

I wonder if this might be one of those use cases where it makes no sense to use the binder at all, and instead do everything manually with signals.

@platosha
Copy link
Contributor

platosha commented Sep 3, 2024

The addValidator() method is unfortunately stateful, so the only way of not producing a memory leak when using it is to only run it once from an effect:

const myField = useFormPart(form.model.myField);
useEffect(() => {
  // Could return a removal callback
  return myField.addValidator(new NotEmpty({message: "Please enter a value"}));
}, []);

Ideally addValidator should throw during React rendering, so that you don't accidentally leak memory.

Would it make sense if the validators are permanently added once, and instead we expose a callback for determining wether a particular field is required for the users? Right now we rely on the presence of the NotEmpty-alike validator (using impliesRequired), but would it be better with explicit callback?

@peholmst
Copy link
Member Author

peholmst commented Sep 3, 2024

Adding a callback would probably help in this case. However, I'm now unsure whether the feature I'm requesting here is just a band-aid while my real issue is somewhere deeper.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request hilla Issues related to Hilla needs design
Projects
None yet
Development

No branches or pull requests

4 participants