Yup get value of ref - yup

I have to calculate something with a reference to another field as part of my yup schema. I figured ref was the way to go, but that doesn't seem to have the actual value I'm trying to use. The only properties of the ref that seems to do what I'm trying to do is getValue which returns the type of the ref, but it requires a parameter of type any. This code snippet should hopefully illustrate my problem and show what I'm trying to do:
const raceSchema = object({
abilityBonuses: array()
.of(
object({
bonus: number()
.min(-10, 'Bonus cannot be lower than -10')
.max(10, 'Bonus cannot be higher than 10')
.required('Bonus is required'),
abilityScore: object({
id: string().required('Ability score id is required'),
name: string().required('Ability score name is required')
})
})
)
.required('Ability bonuses are required'),
abilityBonusOptions: object({
bonus: number()
.min(-10, 'Bonus cannot be lower than -10')
.max(10, 'Bonus cannot be higher than 10')
.required('Bonus is required'),
numberOfAbilities: number().lessThan(
6 -
ref<{ bonus: number; abilityScore: Item }[]>('abilityBonuses').getValue(
// What do I put here? Should I even be using getValue?
).length +
1,
'Sum of number of ability bonuses and ability bonus option number must be less than 6'
)
})
});

You can use the .transform() method to transform the value of a field before validation.
For example, if you have a field called "age" that is a number, you can use the .transform() method to transform the value of "age" into a string before validation:
age: string().transform(value => value.toString()).required()
If you have a field called "age" that is a number, you can use the .transform() method to transform the value of "age" into a string before validation:
age: string().transform(value => value.toString()).required()

Related

omit empty strings fields mongoose

I have the following schema:
const mySchema = new mongoose.Schema({
x: String,
y: String
})
when a user from the front-end requests in his body:
req.body = {
'x' : '',
'y': ''
}
this results in creating a field in MongoDB, but with an empty string.
I need a way to prevent this behavior by setting the empty strings to be undefined somehow.
Is there such an option in Mongoose? or do I have to predict my own middlewares for that?
You could use the set method for Mongoose Schemas:
const mySchema = new mongoose.Schema(
{
myAttribute: {
type: String,
set: (attribute: string) => attribute === '' ? undefined : attribute,
},
},
{ strict: 'throw' },
);
This will unset the field if the string equals ''.
Use this to trim the strings:
set: (a: string) => a?.trim() === '' ? undefined : a
You don't need mongoose, or a middleware to handle this. You can just write a quick few lines to check for empty values and exclude them from the MongoDB write operation.
Ex:
const newEntry = Object.entries(req.body).reduce((obj, [key, value]) => {
if (value) obj[key] = value
return obj
}, {})
In this example, I convert the req.body into an array using Object.entries and iterate over it with the Array.reduce method, wherein I add key:value pairs to a new object if there is a value to add. Since an empty string value is falsey I can do a simple if check on the value. I then assign the return of the reduce method to the variable newEntry. Then I would then take the new entry and create the MongoDB document with it.
This could be extracted into a helper method and reused in any of your routes that need to check remove empty values from an object.
Docs on Array.reduce
Docs on Object.entries

MongoDB field only accepts 3 special values

slider_value: {
type: Number,
required: false,
},
This is the Mongoose schema for one of the fields in my MongoDB model.
It may only accept the integer values of 1, 4, and 10.
How can this validator be specified in the schema?
If you only need to store either one of these three values, storing them as a string, and validating using the enum key would be reasonable. For example that could look like this:
{
slider_value: {
type: String,
enum: ["1", "4", "10"],
},
}
Alternatively, if it is a requirement to store them in form of an int, you could use a custom validator to check a value before it's saved. That would look like this:
{
slider_value: {
type: Number,
validate: {
validator: value => value === 1 || value === 4 || value === 10,
message: props => `${props.value} is invalid for slider_value`,
},
},
}
For more details on custom validators and validation in mongoose in generell, here are the mongoose validation docs.

How to filter an array of object in Mui DataGrid?

I recently changed my tables to Mui-datagrid on Material UI 5, and I have a special use case with an array of objects. I want to enable the phone number filter in this column, but the number is provided as an object list.
phone: [
{ type: "home", number: "795-946-1806" },
{ type: "mobile", number: "850-781-8104" }
]
I was expecting a 'customFilterAndSearch' or an option to customise how to search in this specific field.
customFilterAndSearch: (term, rowData) =>
!!rowData?.suppressedOptions.find(({ description }) =>
description?.toLowerCase().includes(term.toLowerCase())
),
I have made some tries with the filterOperators, but no success yet. I have made a full example here https://codesandbox.io/s/mui-data-grid-vs05fr?file=/demo.js
As far as I can see from the DataGrid documentation I don't see any way to change the filter function for a specific function.
Likely the best workaround for your use case will be converting this to a string be converting the data to a string before you pass it to the datagrid. Though you will lose the styling that you currently do by making the phone type bold.
On second though your best best would probably be to split the phone column into two columns which would probably be the cleanest way of solving your problem
Add helper function.
You could potentially add a helper function to just map all the phone lists to something like mobilePhone or homePhone
const mapPhoneObject = (rows) => {
rows.forEach((row) => {
row.phone.forEach((phone) => {
row[`${phone.type}Phone`] = phone.number;
});
});
return rows
};
I've added a fork of your snippet with my function, it is I think the most viable solution for your problem: https://codesandbox.io/s/mui-data-grid-forked-ppii8y

Can Autocomplete component have different value and option types?

As per docs, Autocomplete component has no distinction between option and actual value.
I have a list of options as objects with ids. When I select an option I want to get its id as a value, not the object itself. Also, when I set the value of Autocomplete I want to pass in id only.
Is it possible?
<Autocomplete
options={[{id: 1, label: 'foo'}, {id: 2, label: 'bar'}]}
value={1}
onChange={(_, value) => { /* value should be number (id) */ }}
/>
Update: option label should remain configurable
Ciao, unfortunately value on onChange event returns one of the options selected. So is not possible to return only one attribute of the element.
The only thing you can do is take the value.id:
<Autocomplete
options={[
{ id: 1, label: "foo" },
{ id: 2, label: "bar" }
]}
getOptionLabel={(option) => option.label} // this to show label on Autocomplete
getOptionSelected={(option, value) => option.id === value.id} // this to compare option on id value
onChange={(event, value) => console.log(value.id)} // here access to id property of value object
...
/>
Here a codesandbox example.

Extjs form.submit() call changing field value

I can see what are the values of the fields just before the submit:
var itemsForm = '';
function mostraItems(item, index, length) { itemsForm += item.id + ':' + item.name + ':' + item.value + ':' + index + '\n'; }
myForm.form.items.each(mostraItems);
alert (itemsForm);
myForm.form.submit({...
The problem I have is that the submitted values are different from what I can see before the form.submit() call. One of the fields is a ComboBox:
var myCombo = new Ext.form.ComboBox({
//autoWidth: true,
width: 250,
displayField: 'theFieldText',
editable: false,
emptyText: 'Select something ...',
fieldLabel: 'Some text',
listeners: { 'select': { fn: theOnSelect, scope: this} },
mode: 'local',
selectOnFocus: true,
store: theStore,
triggerAction: 'all',
typeAhead: true,
valueField: 'theFieldValue',
name: 'fieldName'
});
What is going in the request is the sum of the valueField and the displayField. Say the value field contains "1" and the displayField contains "some text" then what goes in the request is "1 (some text)" in instead of just the value "1".
There is something happening after or during the form.submit() call and I can't find what it is.
Using Ext 2.3
There isn't anything unusual happening during form submit call.
First of all, check the form values just before the form is submitted (but not the way you do it now). Do you use Firebug (I hope yes)?
myForm.getValues();
gives you key/value pairs as they will be submitted.
So type into console
Ext.getCmp('your-form-id').getForm().getValues();
or put into your code
console.log(myForm.getValues());
instead of alert() and see an output. Then, when you submit the form in a standard way
myForm.submit({url: 'submit-url'})
there is no chance your values will be different. How do you submit the form?
As Igor described, you should always use form.getForm().getValues() to see what Values are being submitted.
And if for any particular field you are not happy with the way your data is being formatted or displayed or calculated, you can always override the getSubmitData method for that field.