In my code, I have this DropdownFormField so the user can select their gender:
DropdownButtonFormField<String>(
decoration: InputDecoration(labelText: 'Select gender'),
validator: (val) => val!.isEmpty ? 'Fill the field' : null,
isExpanded: true,
value: _selectedValue,
items: items.map(buildMenuItem).toList(),
onChanged: (val) {
setState(() {
gender = val;
});
},
)
in onChanged: (val), val is expected to be a String?, but gender is a String. is a use val as String as gender = val as String, apparently it works. But, if I press the save button without selecting an option, I get an error:
Null check operator used on a null value
As if the item isn"t going through validator
The ! operator after a nullable value tells flutter to assume the value is not null and to throw an error if it is.
(val) => val!.isEmpty ? 'Fill the field' : null,
so when you call this with an empty option, it throws an error because val is null at this point in time. To fix this, simply change the validator to something like this:
(val) => (val==null || val.isEmpty) ? 'Fill the field' : null,
Also, something else is that there is no need to say val as String if your type is String?, that is literally the reason why ! exists, for situations in which you already know a nullable value is not null:
gender = val!;
Related
I have this code
#Get()
#ApiQuery({
name: "code",
type: String,
required: false,
})
#ApiQuery({
name: "id",
type: Number,
required: false,
})
async read(
#Query("entity") entity: string,
#Query("code") code: string,
#Query("id", ParseIntPipe) id: number
): Promise<Q> {
return this.service.readAsync({ where: { codigo: code, id: id } });
}
Why I'm getting Validation failed (numeric string is expected) when I request to http://localhost:3000/api/v1/endpoint?entity=a&code=b
I know is related with id param, but I don't know how to solve this.
I want to be able to use code or id params according my needs.
If I request to http://localhost:3000/api/v1/endpoint?entity=a&code=b&id=1 or http://localhost:3000/api/v1/endpoint?entity=a&id=1 all is fine.
here #Query("id", ParseIntPipe) id: number you're saying that the query parameter id is required and must be an integer.
Thus, if you do GET /endpoint?entity=a&code=b, it will reply with bad request as there's no id parameter.
You can use the DefaultValuePipe pipe if id should be optional and will have a fallback value.
If you don't want any default value, then you'll need to write your own pipe (that could extends ParseIntPipe). Or you could use the builtin one ValidationPipe with class-validator decorators.
ParserIntPipe doesn't work on optional parameters, from its source code, you can see
async transform(value: string, metadata: ArgumentMetadata): Promise<number> {
if (!this.isNumeric(value)) {
throw this.exceptionFactory(
'Validation failed (numeric string is expected)',
);
}
return parseInt(value, 10);
}
/**
* #returns `true` if `value` is a valid integer number
*/
protected isNumeric(value: string): boolean {
return (
['string', 'number'].includes(typeof value) &&
/^-?\d+$/.test(value) &&
isFinite(value as any)
);
}
As per Micael Levi answer, you either provide a default value using DefaultValuePipe in case it was missing, or you build your own custom pipe that pass parameter undefined value
How I can ignore the error like validation failed: gender: "" is not a valid enum value for path gender when receive a empty value to save into database
My schema look like:
Person {
gender: {
type: String,
enum: ['men', 'women'],
required: false
}
}
In my code (NodeJS)
I have a check:
if (body.gender && !['men', 'women'].includes(body.gender.toLowercase())) {
throw Error("Gender invalid");
}
await savePerson(body);
If have to lowerCase value to check in case insensitive
I think in Javascript empty string is not same with null or undefined, so the error is not throw. I don't want to check !isNullOrUndefined(body.gender) as well. But in process save to mongo, error validation failed: gender: "" is not a valid enum value for path gender has been threw by mongoose
The first condition in your if is true when body.gender is not null or undefined or empty string "". So these values pass your validation and go to the .save() function
You can change to this, it will catch the invalid values above :
if (!['men', 'women'].includes(body.gender)) {
throw Error("Gender invalid");
}
console.log(!['men', 'women'].includes(undefined)); // true
console.log(!['men', 'women'].includes(null)); // true
console.log(!['men', 'women'].includes("")); // true
Edit: So, the condition is "the gender is string and is one of "men", "women" case insensitive". I suggest this validation:
if (typeof(body.gender) !== "string" || !['men', 'women'].includes(body.gender.toLowerCase())) {
throw Error("Gender invalid");
}
Below I run some test:
function isValidGender(gender) {
if (typeof(gender) !== "string" || !['men', 'women'].includes(gender.toLowerCase())) {
console.log("Error");
} else {
console.log("Valid");
}
}
isValidGender(undefined);
isValidGender(null);
isValidGender("");
isValidGender("Men");
isValidGender("wOmEn");
isValidGender("AA");
I am learning flutter and getting so many errors with flutter...
I am trying to get a validation of text fields with the following methods:
validateName() {
String value = '';
if (value.isEmpty) return 'Username is Required.';
final RegExp nameExp = new RegExp(r'^[A-za-zğüşöçİĞÜŞÖÇ ]+$');
if (!nameExp.hasMatch(value))
return 'Please enter only alphabetical characters.';
return value;
}
However, I am getting the above mentioned error on validationFunction in the textformbuilder:
TextFormBuilder(
enabled: !viewModel.loading,
prefix: Feather.user,
hintText: "Username",
textInputAction: TextInputAction.next,
validateFunction: validateName(),
onSaved: (String val) {
viewModel.setName(val);
},
focusNode: viewModel.usernameFN,
nextFocusNode: viewModel.emailFN,
),
Thanks in advance!
validate function is different from your function...so change the function validate name
String validateName(String? value) {
if (value!.isEmpty) return 'Username is Required.';
final RegExp nameExp = new RegExp(r'^[A-za-zğüşöçİĞÜŞÖÇ ]+$');
if (!nameExp.hasMatch(value))
return 'Please enter only alphabetical characters.';
return value;
}
and on the textfield builder...put the validateFunction like this
TextFormBuilder(
validateFunction: validateName,
)
I have a simple Schema
const MediaElementSchema = {
primaryKey: 'id',
name: 'MediaElement',
properties: {
id: 'int',
type: 'string',
path: 'string'
}
}
When I try to get all:
let elements = realm.objects('MediaElement')
Realm returns the results in an object like below:
{"0": Record1, "1" : Record2, etc}
is there a way for realm to return an array of the elements like:
[Element1, Element2, etc]
I checked the documentation but didn't find anything relevant about the return type.
https://realm.io/docs/javascript/latest
You could just use plain old javascript to convert object into array.
let elements = {'0': 'Record1', '1' : 'Record2'};
elements = Object.keys(elements).map(key => elements[key]);
console.log(elements); // ["Record1", "Record2"]
I have a mongoose schema where I'm storing a port number. I also have a default value set for the field.
port:{
type:Number,
default:1234
}
If I don't get any value via my API, it gets set to 1234.
However, If someone sends null, it accepts null and saves to database.
Shouldn't it covert null to 1234? null is not a number! Am I understanding it wrong?
I am considering the solution given here, but I dont want to add extra code for something that should work without it (unless I'm wrong and its not supposed to convert null to 1234)
See the comments in this issue:
https://github.com/Automattic/mongoose/issues/2438
null is a valid value for a Date property, unless you specify required. Defaults only get set if the value is undefined, not if its falsy.
(it's about dates but it can be applied to numbers just as well.)
Your options are to either:
add required to the field
add a custom validator that would reject it
use hooks/middleware to fix the issue
You might get away with a pre-save or post-validate (or some other) hook like this:
YourCollection.pre('save', function (next) {
if (this.port === null) {
this.port = undefined;
}
next();
});
but probably you'll have to use something like:
YourCollection.pre('save', function (next) {
if (this.port === null) {
this.port = 1234; // get it from the schema object instead of hardcoding
}
next();
});
See also this answer for some tricks on how to make null trigger default values in function invocation:
Passing in NULL as a parameter in ES6 does not use the default parameter when one is provided
This is unfortunate that Mongoose cannot be configured to tread null as undefined (with some "not-null" parameter or something like that) because it is sometimes the case that you work with data that you got in a request as JSON and it can sometimes convert undefined to null:
> JSON.parse(JSON.stringify([ undefined ]));
[ null ]
or even add null values where there was no (explicit) undefined:
> JSON.parse(JSON.stringify([ 1,,2 ]));
[ 1, null, 2 ]
As explained in mongoose official docs here
Number
To declare a path as a number, you may use either the Number global constructor or the string 'Number'.
const schema1 = new Schema({ age: Number }); // age will be cast to a Number
const schema2 = new Schema({ age: 'Number' }); // Equivalent
const Car = mongoose.model('Car', schema2);
There are several types of values that will be successfully cast to a Number.
new Car({ age: '15' }).age; // 15 as a Number
new Car({ age: true }).age; // 1 as a Number
new Car({ age: false }).age; // 0 as a Number
new Car({ age: { valueOf: () => 83 } }).age; // 83 as a Number
If you pass an object with a valueOf() function that returns a Number, Mongoose will call it and assign the returned value to the path.
The values null and undefined are not cast.
NaN, strings that cast to NaN, arrays, and objects that don't have a valueOf() function will all result in a CastError.