Override value in the form using yup when condition applies - javascript

I am trying to build a yup validation schema, but I couldn't figure out how to transform value to a default every time when it doesn't match the schema.
I was trying to check is value higher than 0 and not undefined, so then this form value would be required, otherwise I would like to set it to the empty string.
This is my code:
reason: string()
.when('value', {
is: val => Boolean(val),
then: string().required('This field is required'),
otherwise: string().transform((value) => value ? value : '')
})
Thanks a lot!

Related

How to cast a string into an array using Yup

So whenever I receive a string I want to store it as an array. But I've got no luck so far, i tried to do with cast and with transform. I just need some clarity to get the things going.
Is transform and cast the same thing? How to cast a string into an array using Yup?
const schema = yup.object().shape({
types: yup
.array('type must be an array.')
.of(
yup
.string('the array must contains only strings.')
.transform(value =>
typeof value === 'string' || value instanceof 'string'
? [value]
: value,
)
.matches(/(writer|artist)/, null),
)
.min(1, 'Need to provide at least one type')
.max(2, 'Can not provide more than two types'),
name: yup
.string('name must be a string.')
.min(3, 'too short'),
});
let obj = {
name: 'Kentarou Kishima',
types: 'artist',
}
//returns ValidationError
obj = schema.cast(obj, { stripUnknown: true });
//trying to just validate results in the same error
schema
.validate(obj)
.then(() => {
next();
})
.catch(function (e) {
console.log(e);
return something;
});
ValidationError: types must be a array type, but the final value was: null (cast from the value "artist")
Edit:
I fixed minor typo btw.
Well, I removed the matches line and it keeps returning the same Error. So now I am thinking since it's receiving a string and not an array, when it goes into the transform function it is going to search for the array items to cast, but there's none because it got a string. So it's well likely that the transform function should be side-by-side with array() and not inside it.
The code looks like this now, but I'm still getting the Error with or without matches():
.array('types must be an array.')
.of(
yup
.string('the array must contains only strings.')
.matches(/(^writer$|^artist$)/) //I improved the regex pattern
)
.transform(value =>
typeof value === 'string' || value instanceof String
? [value]
: value,
)
.min(1, 'Need to provide at least one type')
.max(2, 'Can not provide more than two types'),
To make things clearer, these are the type of input I am expecting:
let obj = {
name: 'Kentarou Kishima',
types: 'artist', //should cast
types: ['artist'], //should pass
types: ['artist', 'writer'], //should pass
types: '', //should reject
types: ['something'], //should reject
types: ['artist', 'something', 'writer'], //should reject
types: ['artist', 'artist'], // should reject, but i will put a test() later on.
}
The order of operations on the types property is out of order. It follows:
Ensure array element is string.
If the value is a string, convert it to an array containing itself.
If the array of the single string matches the regular expression, continue. If it does not, report null.
If you truly want an array of single-element arrays, then you can keep the transform, but you'll want to move the matches() above the transform() as the arrays that result from the transform() will never match the regular expression, and so matches() always returns your null.
const schema = yup.object().shape({
types: yup
.array('type must be an array.')
.of(
yup
.string('the array must contains only strings.')
.matches(/(writer|artist)/, null)
.transform(value =>
typeof value === 'string' || myVar instanceof 'string'
? [value]
: value,
),
)
.min(1, 'Need to provide at least one type')
.max(2, 'Can not provide more than two types'),
name: yup
.string('name must be a string.')
.min(3, 'too short'),
});
After messing around with the documentation I found the answer. In this case is enough to use the ensure() function, basically it will take anything that is not an array and put it into an array. After that, the matches() function will reject anything that does not follow the regex pattern.
yup
.array('types must be an array.')
.of(
yup
.string('the array must contains only strings.')
.matches(/(^writer$|^artist$)/)
)
.ensure()
.min(1, 'Need to provide at least one type')
.max(2, 'Can not provide more than two types'),
Edit:
Just a disclaimer, the way it is with min(1) enabled, this property always will be required even though there's no required(), even specifying notRequired() in the object doesn't do the trick.
This is a known issue in yup
https://github.com/jquense/yup/issues/1267
In my case, I need this validator for my POST (all required) and PUT (at least one required) requests, in POST requests I use it the way it is, in PUT requests I dynamically add the rules checking for those present in the req.body.

Node js Joi validation conditional disallow keys

I am new to nodeJS, so forgive me if my question sounds stupid,
I want to support conditional payload based on another key,
price: Joi.when('pricing', {
is: 'VARIABLE',
then: Joi.number()
.min(1)
.max(1000)
.required(),
otherwise: // prevent adding price in the payload
})
I want the user to provide price value if pricing is equal to 'VARIABLE' otherwhise to prevent user providing price in the payload.
From the Joi Documentation, we can use the Joi.forbidden() or Joi.any().forbidden() to disallow any keys in your schema. In your case, your final schema will be:
price: Joi.when('pricing', {
is: 'VARIABLE',
then: Joi.number().min(1).max(1000).required(),
otherwise: Joi.forbidden()
})

Firestore select where is not null

I'm using firebase to manage my project and I cannot get to create a query with a where clause where some value is not null.
Example: I have a collection of employees. Each have a list of equipments as an object where the key is the equipment id and the value a color.
user = {
firstName: 'blabla',
lastName: 'bloblo',
equipments: {
123: 'blue',
124: 'red'
}
}
I would like to get all the employees who has a certain equipment in the equipments. Lets say 123.
It comes to Select * from Employees where equipments.123 is not null. I've tried:
firestore.collection('employees').where(`equipments.${equipmentId}`, '!=', null)
but it's not working.
I can't seems to make it work. Can you help me.
Update Sep 2020: v7.21.0 introduces support for not equals (!=) queries!
That means you can now use the code bellow:
firestore.collection('employees').where(`equipments.${equipm‌​entId}`, '!=', null)
Previous answer:
Firestore has no "not equal" operator. But looking at the logic, what you're trying to do is query for values which are String, and not null. Firestore can do that if you pass a String to the where() function.
So what you can do is query for values lower than \uf8ff. That's a very high code point in the Unicode range. Since it is after most regular characters in Unicode, this query will return everything that is of type String:
firestore.collection('employees').where(`equipments.${equipm‌​entId}`, '<', '\uf8ff')
Or you can simply query for values higher than "" (empty String):
firestore.collection('employees').where(`equipments.${equipm‌​entId}`, '>', '')
FWIW since Firestore indexes are sparse [1] you can do something like:
firestore.collection('employees').orderBy(`equipments.${equipm‌​entId}`)
And you'll only get documents where that field is set. If you're explicitly setting the fields to null in your database, however, you'll get null values first, so if you want to avoid explicit null values you can do:
firestore.collection('employees').orderBy('equipments.${equipm‌​entId}').startAfter(null);
[1]: Sparse in the sense that if the field is not present in the document, Cloud Firestore does not create an index entry in the index for that document/field.

Javascript formatting null value in table cell

I have the following snippet within my react component that passes in a transaction object with several fields. Why does it not work?
I'm trying to only show a value formatted with a $ sign if the value is not null.
${!isNaN(transaction.debit) ?
parseFloat(transaction.debit).toFixed(2) : null}
Is there a better way to do this? My array of data basically has debit fields that may not have a value and in that case I just don't want to display anything in the cell.
How about concatenating the string '$' to the beginning of your float if the transaction.debit value is Truthy or it is 0 (assuming we want to show a value for 0) - otherwise show an empty string.
{transaction.debit || transaction.debit === 0 ? '$' + parseFloat(transaction.debit).toFixed(2) : ''}

How to set a default value

Here is how I extend the Immutable.Record
import Immutable from 'immutable';
const DATA_DEFAULTS = {
id: String,
data: String,
ref_id: String,
};
export default class Data
extends Immutable.Record(DATA_DEFAULTS) {}
If the json representation does not contain ref_id, then when I try to print the value of the field in the console of Chrome devtool, I will get:
> data.ref_id
String() { [native code] }
I think it is the reason why I cannot filter out entities with empty ref_id in a list
a = [] // a list of data
b = a.filter(x => x.ref_id != '') // b is the same as a
I suppose it can be fixed by either:
set a default value to a field in the Immutable.Record instance when the field is missing in the json data
use another way to detect if the field is not set in the instance
For the second approach, I have tried, for example, data.has('ref_id') and it always report true regardless if the field has any valid value.
My questions:
1) Can I set a default value in a Immutable.Record?
2) How to filter on field that may or may not exist in the Immutable.Record
3) What is the right way to test the existence of valid value in a field in an instance of Immutable.Record?
You are explicitly setting the default values of each of the fields to the function String. String is not a data type here, if that's what you thought. What you seem to want is
const DATA_DEFAULTS = {
id: '',
data: '',
ref_id: '',
};
1) Can I set a default value in a Immutable.Record?
Exactly how you already did, you just need to set the correct default value.
2) How to filter on field that may or may not exist in the Immutable.Record
Fields on a record always exist. From the docs:
Records always have a value for the keys they define. removeing a key from a record simply resets it to the default value for that key.
3) What is the right way to test the existence of valid value in a field in an instance of Immutable.Record?
You can use a default value that you know would not be explicitly assigned to the field otherwise. That could be null or a symbol.

Categories

Resources