Combine Number AND Enum
Drulac opened this issue Β· comments
Package version
1.8.0
Describe the bug
Hello π !
Sorry, Github won't let me use the Feature Request
issue type, forced to submit it as Bug Report
:-/
TLDR
[β¨ New feature] : Requesting Number (to autoconvert HTML form string to number) and Enum (to ensure the number is from a predefined list) types combination, like this :
vine.number().enum([1, 3, 4, 8])
A bit of the request context
If I want to let my user choice between some objects (already in database, to use as relation) I could use an HTML select, and (dynamicly, using a template) pass every object id as value :
<select name="objectId" id="objectId">
<option value="1">A Choice</option>
<option value="3">B Choice</option>
<option value="4">C Choice</option>
<option value="8">D Choice</option>
</select>
Because in HTML forms, the values are always strings. My form will send "1"
, "2"
or "3"
(or whatever if the user alter the form).
If I want to save in DB a correct objectId
for the relation, I need to convert the objectId
from string to Number
, and then check if there is actually an object with this id
in my database.
Using number().range
instead of enum
isn't possible because some object's id are unavailables.
It give me (using AdonisJS) a controller store method like that :
async store({ request }: HttpContext) {
const data = request.all()
//converting string to number
if (data.objectId) {
data.objectId = parseInt(data.objectId)
}
//getting all corrects objects id from DB
const availableObjectIds = (await Object.all())
.map((obj) => obj.serialize().id)
//should be equal to [1, 3, 4, 8]
data.availableObjectIds = availableObjectIds
const payload = await Validator.validate(data)
return Objet.create(payload)
}
With a Validator
like that :
export const Validator = vine.compile(
vine.object({
objectId: vine.enum((field) => {
//taking our ids picked from DB
//should be equal to [1, 3, 4, 8]
return field.parent.availableObjectIds
}),
})
)
With number and enum combined
I could drop theses lines from the controller :
//converting string to number
if (data.objectId) {
data.objectId = parseInt(data.objectId)
}
async store({ request }: HttpContext) {
const data = request.all()
//getting all corrects objects id from DB
const availableObjectIds = (await Object.all())
.map((obj) => obj.serialize().id)
//should be equal to [1, 3, 4, 8]
data.availableObjectIds = availableObjectIds
const payload = await Validator.validate(data)
return Objet.create(payload)
}
And my validator will simply look like that :
export const Validator = vine.compile(
vine.object({
//converting string to number
objectId: vine.number().enum((field) => {
//taking our ids picked from DB
//should be equal to [1, 3, 4, 8]
return field.parent.availableObjectIds
}),
})
)
I'm asking this feature because I think it's better to keep data type validation inside models definitions
Thanks for all your work on the Adonis environnement !
Reproduction repo
No response
How about using the number schema with the in
validation rule. Something like this
vine.number().in([1, 3, 4, 8])
Do note, the in
validation rule does not exists, but it can be added
It could do the job very well π !