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

Validating/Modifying new input before writing it to varaible from v-model #7969

Open
HonzaKubita opened this issue Mar 28, 2023 · 6 comments
Labels
✨ feature request New feature or request

Comments

@HonzaKubita
Copy link

What problem does this feature solve?

Before I say anything this might be that I am not skilled enough in vue an there is a way to do this already.

Context:

The issue I'm having is that I have a variable price (reactive object)
{ min: 0, max: 0 }
I have two range inputs that each modify those values.
Then I have two normal number inputs that display the value and allow user to modify them if the desired value is too hard to get right with just the slider.
The there is a maximum price (set by the most expensive product) and minimum price (defalult 0)

template:

<input type="number" v-model="price.max">
<input type="number" v-model="price.min">

<input type="range" min="0" max="maximum" v-model="price.max">
<input type="range" min="0" max="maximum" v-model="price.min">

script setup:

const maximum = 1000;

const price = reactive({
  min: 0,
  max: 1000
});

The problem:

First thing that I had coded was only the sliders so the user was limited by the sliders max and min properties from html
But right now when I added the number inputs the user is not limited to anything and everything breaks when they enter too large number.

The solution:

In vue we already have modifications of v-model like v-model.number="targetVar"
What I would like to see is this type of thing but user defined something like v-model.validate(functionFromScript)="targetVar"
This would call the function from script which would return either true or false and that will decide if the value is going to get changed or not.
This could also introduce another thing like v-model.modify(frunctionFromScript)="targetVar"
What this would do is that the value would get processed and modified by user defined function. It would work the same as v-model.number="targetVar" because what I assume is that .number calls the Number() constructor on the input before passing it down the code.

Conclusion:

I know there is a way to kinda do this with writable computed but from what I heard writable computed is not a good thing to use and it cannot be used as cleanly and isn't as reusable as this solution. This solution could also allow the user to stack the functions and reuse them.

This feature would be used every time you want to protect your raw data in script because you cannot assume that user would enter only valid input. Some browsers even ignore the input type for example I think that firefox allows the user to enter characters into number inputs

What does the proposed API look like?

<template>

<input type=number v-model.number.validate(rangeValidation)="validatedNumber">

</template>

<script setup>
const max = 1000;
const min = 0;

const validatedNumber = ref(0);

function rangeValidation(input) {
  if (input > max) return false;
  if (input < min) return false;
  // More test cases
  return false;
}

</script>
@HonzaKubita HonzaKubita added the ✨ feature request New feature or request label Mar 28, 2023
@baiwusanyu-c
Copy link
Member

It seems that you want to be able to define a verification function when the v-model is updated. If the data verification fails, it will not be updated.
In my opinion, v-model on the native dom does not seem to have this ability, you can do a high-level component package to achieve your needs (https://vuejs.org/guide/components/v-model.html# handling-v-model-modifiers), in vueuse, the v-model of the component can be verified before emit (vueuse/vueuse#2836)

@HonzaKubita
Copy link
Author

That's why is it a feature request, I think you could say that you can use high level stuff about everything. The thing is (as I pointed out in the request) that vue already almost has this functionality just doesn't allow to make user defined modifiers. And I want to be able to use this without having to use components because I don't want to emit the value because it would be useless unless I was already doing it.

@tho-daskalakis
Copy link

You could add a listener for value changes in your input, that would call the validate function and update your data. Then you could bind your input to your variable. Basically skip v-model (two way binding) and use v-bind (one way bind) instead, with a listener.

@HonzaKubita
Copy link
Author

HonzaKubita commented Apr 19, 2023

@tho-daskalakis That would get messy with multiple validators or modifiers. I'm not looking for alternative ways to do this. You could say we don't need router as we could do v-if on every page and then have a variable which determined on which page are we. I'm requesting it because it already is in vue it just cannot be made custom.

@tho-daskalakis
Copy link

You should be having different validators for different inputs anyways. In your requested feature, you would be using multiple validators as well. The example you mentioned with vue-router vs v-if is not accurate, as in vue-router you have extra functionality, like lazy loading.

If you are concerned about a component becoming too complex and bloated, why not break it up to different input components, each one with their own validators? I see this would be a different way of writing a single directive v-model.validate.validateValue="value" instead of two different ones :value="value" @input="validateValue", but the functionality is already there, and the proposed feature doesn't seem to reduce complexity imo.

@HonzaKubita
Copy link
Author

First of all how do you want to break up one input into multiple ones that's my first question.
And right now this would make it more readable. Right now if you would like to chain those validation methods you would have to make functions that call each other and the last would change the value. With my solution you would just define function that would return either true or false depending if the input passed the validation, or modify the value if it is a modifier not validator.
This would introduce opportunity for libraries with validating functions that you could just import and use in the template.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
✨ feature request New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants