How to set defaultValue for multi select? - react-select

So, I need to pass defaultValue to a react-select component with enabled multi select. I've tried everything I could think of: array of strings, array of objects, string, etc... Nothing seems to work.
I'm also using the getOptionLabel and getOptionValue, might they be the cause for all this mess?

If you refer to react-select documentation, the way to set defaultValue to multiple value select:
<Select
defaultValue={[colourOptions[2], colourOptions[3]]}
isMulti
name="colors"
options={colourOptions}
className="basic-multi-select"
classNamePrefix="select"
/>
The structure of options is
[
{
label: <string>,
value: <string>,
}
]
Working example here.

There is an alternate way to use value as your defaultValue.
In my case I have used "id" and "industry" instead of "label" and "value"
this.state = {
interested_industries: [{id:"ANY", industry:"ANY"}]
}
And in Select component:-
<Select
name="interested_industries"
options={industries}
value={interested_industries}
getOptionLabel={ x => x.id}
getOptionValue={ x => x.industry}
onChange={this.handleSelect}
isMulti
/>

defaultValue accepts an object or array of objects.
here an object can be like this :
defaultValue = {{ value: 0, label: "John" }}
This is also one way:
defaultValue = { array1[0] }
If you want array of objects for multiple options (isMulti) you can do this:
defaultValue = { array1.map(ele => ele) }
Where array1 is an array of objects.
array1 = [
{ label: "John", value: 0 },
{ label: "Indiana", value: 1 },
{ label: "Stark", value: 2 },
];
This solution worked for me. I hope this helps you too.

You can set defaultValue without index
<Select
defaultValue={existingItems}
onChange={(option) => onChangeSelect(option)}
closeMenuOnSelect={false}
components={animatedComponents}
isMulti={true}
options={options}
/>
But for this to work you need await loading items from defaultValue if you loading from server
For Example my full code
{!kindsByRestaraunt.loading ? (
<Select
defaultValue={existingItems}
onChange={(option) => onChangeSelect(option)}
closeMenuOnSelect={false}
components={animatedComponents}
isMulti={true}
options={options}
/>
): ""}

According to React documentation, you can do this:
<select multiple={true} value={['B', 'C']}>
Where B, C are the default value you want to have selected.

Related

Sequelize raw query update array of objects as replacements

I am using sequelize (postgres) and I need to properly escape a query like this:
`
UPDATE "Pets"
SET "name" = CASE LOWER("name")
${input.pets
.map((pet) => `WHEN '${pet.name.toLowerCase()}' THEN '${pet.newName}'`)
.join('\n')}
ELSE "name"
END
WHERE LOWER("name") IN(${input.pets
.map((pet) => `'${pet.name.toLowerCase()}'`)
.join(',')});
`
Sample input.pets:
[{ name: "rocky", newName: "leo" }]
Does anyone have an idea how to achieve this with replacements?
I have found a thread on github which suggested something like this:
let data = [ [ 252456, 1, 55, '0' ],
[ 357083, 1, 56, '0' ],
[ 316493, 1, 57, '0' ] ];
db.query(
`INSERT INTO product (a, b) VALUES ${data.map(a => '(?)').join(',')};`,
{
replacements: data,
type: Sequelize.QueryTypes.INSERT
}
);
However, a 2d array is being used here not an array of objects. Is there a way to access individual properties from the array? When I try something like this
`
UPDATE "Pets"
SET "name" = CASE LOWER("name")
${input.pets
.map((_pet) => `WHEN ? THEN ?`)
.join('\n')}
ELSE "name"
END
WHERE LOWER("name") IN(${input.pets
.map((_pet) => `?`)
.join(',')});
`,
{ type: QueryTypes.UPDATE, replacements: input.pets },
The first ? turns out to be the whole object. Is there a way to access it's properties?
I also tried transforming input.pets into a 2d array but still couldn't get it to work as in example with insert above.
In advance thanks for your time
const names = input.pets.map((pet) => pet.name);
const newNames = input.pets.map((pet) => pet.newName);
`
UPDATE "Pets"
SET "name" = CASE LOWER("name")
${names.map((_) => `WHEN LOWER(:names) THEN :newNames`).join('\n')}
ELSE "name"
END
WHERE LOWER("name") IN(${names.map((_) => `LOWER(:names)`).join(',')});
`,
{ replacements: { names, newNames } },
This works. In cases like this it's better to work with simpler data structures. Another option I found is using sequelize.escape() built-in function, but it's not documented so I decided not to
EDIT:
After some testing, this works but for only one object in the input
If the input looks something like this:
[
{ name: "rocky", newName: "fafik" }
{ name: "asd", newName: "qwerty" }
]
Then in resut I get queries like this:
WHEN LOWER('rocky', 'asd') THEN 'fafik', 'qwerty'
WHEN LOWER('rocky', 'asd') THEN 'fafik', 'qwerty'
So it doesn't loop over arrays. Still the problem remains, how to access individual properties, whether from array or an object?
EDIT2: FINAL ANSWER
sequelize.query(
`
UPDATE "Pets"
SET "name" = CASE LOWER("name")
${input.pets.map(() => `WHEN ? THEN ?`).join('\n')}
ELSE "name"
END
WHERE LOWER("name") IN(?);
`,
{
replacements: [
...input.pets.flatMap((x) => [x.name.toLocaleLowerCase(), x.newName]),
input.pets.map((x) => x.name.toLocaleLowerCase()),
],
},

How to show icon next to value in cloumn in aurelia slickgrid/slickgrid?

I want to show en edit icon next to value in Amount column. This is because the Amount column is actually editable.But to give that as a hint to user, i want to show some edit icon next to it. How to do that in aurelia slickgrid?
Or maybe there is a way to highlight a field on hover ?
I am using aurelia slickgrid and looking if there is some option in aurelia slickgrid itself.
Go to the aurelia slickgrid example link and click on the link of example's source code
When you open it, there is a method called defineGrids
/* Define grid Options and Columns */
defineGrids() {
this.columnDefinitions1 = [
...,
...,
...,
...,
...,
{ id: 'effort-driven', name: 'Effort Driven', field: 'effortDriven', formatter: myCustomCheckmarkFormatter, type: FieldType.number, sortable: true, minWidth: 100 }
];
... rest of the code
}
The row with id effort-driven is where the icons are placed. On the other words, when you push a data collection(usually array of json object) to the table, values of the data objects with key name effort-driven are given to column with id effort-driven. Furthermore, for each passed value to the column, the method myCustomCheckmarkFormatter reformat it(for example 0 -> false or null -> not filled) and place it to the corresponding table's cell. look at the below method:
// create my custom Formatter with the Formatter type
const myCustomCheckmarkFormatter: Formatter<DataItem> = (_row, _cell, value) => {
// you can return a string of a object (of type FormatterResultObject), the 2 types are shown below
return value ? `<i class="fa fa-fire red" aria-hidden="true"></i>` : { text: '<i class="fa fa-snowflake-o" aria-hidden="true"></i>', addClasses: 'lightblue', toolTip: 'Freezing' };
};
As you can see, when the method is called, it returns an icon such as <i class="fa fa-fire red" aria-hidden="true"></i> which is placed in the table's cell.
I added an edit icon next to Amount,
{
id: "Edit",
field: "edit",
excludeFromColumnPicker: true,
excludeFromExport: true,
excludeFromQuery: true,
excludeFromGridMenu: true,
excludeFromHeaderMenu: true,
minWidth: 30,
maxWidth: 30,
formatter: Formatters.editIcon,
},
and used this custom format from ghiscoding comment:
const customEditableInputFormatter: Formatter = (_row, _cell, value, columnDef, dataContext, grid) => {
const isEditable = !!columnDef.editor;
value = (value === null || value === undefined) ? '' : value;
return isEditable ? `<div style="background-color: aliceblue">${value}</div>` : value;
};
The result is as shown in the picture.

VueJS2: How to pluck out one property of an array and use it to find matching value in the second array?

I have two arrays. I am trying to pluck out a property from one array and use it to find the value of another property in the other way. How to do this? Let me explain:
I have an array of objects that looks like so:
languageCodes:
{
"code1234char3": "mdr",
"name": "Mandar",
},
{
"code1234char3": "man",
"name": "Mandingo",
},
{
// etc...
},
I have another array of objects that looks like so:
divisionLanguages:
[
{
p_uID: 1,
nameLang3Char: 'mdr',
},
{
p_uID: 2,
nameLang3Char: 'man'
},
{
// etc..
}
]
I have a Vue template with an unordered list like so:
<ul v-for="x in divisionLanguages" :key="x.p_uID">
<li>Name: FOO
<li>Language: {{x.nameLang3Char}} - XXX</li> <--how to get 'name' value from 'languageCodes' and place here?
</ul>
Expected output should be:
Name: FOO
Language: mdr - Mandar
Name: BAR
Language: man - Mandingo
I tried to do something like in Vue SFC template (but did not work):
<li>Language: {{ languageName(x.nameLanguage3Char) }}</li>
...
methods: {
languageName(nameLanguage3Char) {
const name = this.divisionLanguages.filter(x => x.code6392char3 === nameLanguage3Char)
return name.name
}
I hope this makes sense of what I am trying to do.
Update: Thanks to #kellen in the comments, I change from filte() to find() like so:
languageName(nameLang3Char) {
const languageName = this.languageCodes.find(
x => x.code1234char3 == nameLang3Char
)
return languageName
},
and in I did:
<li>Language: {{ languageName(x.nameLang3Char).name }}</li>
and it works...but I get error in console:
Error in render: "TypeError: Cannot read property 'name' of undefined"
Have you tried combining these arrays before rendering them? If you were able to combine both objects before creating that list, that would make your life easier. Another thing I noticed is you're using filter, when find might be a better option to return a single value rather than an array. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find

Filter Vue list based on select option value

I try to filter my list with 2 select lists based on the selected value. It seems like my computed filter is not working?
You should be able to filter the list on 'Price from' and 'Price to'
List.vue
My computed filter property:
filteredData() {
const LowerCaseSearch = this.search.toLowerCase();
return this.products.filter(
product =>
(product.name.toLowerCase().includes(LowerCaseSearch) ||
product.category.toLowerCase().includes(LowerCaseSearch)) &&
(!this.checked.length || this.checked.includes(product.category)) &&
(!this.selectedFrom.length || this.selectedFrom.includes(product.price)) &&
(!this.selectedTo.length || this.selectedTo.includes(product.price))
);
},
In my registered component I use v-model to bind to the computed property selectedFrom
<Price v-model="selectedFrom" />
How do I bind to the other property selectedTo in one v-model and what's wrong with my filter?
I also use a prefix 'From' and 'To' to put in front of the options.
data: () => {
return {
selectedFrom: '0,00',
priceFrom: [
{ prefix: 'From', text: '0,00', value: '0,00' },
{ prefix: 'From', text: '200,00', value: '200,00' },
{ prefix: 'From', text: '400,00', value: '400,00' }
],
selectedTo: 'No max',
priceTo: [
{ prefix: 'To', text: '400,00', value: '400,00' },
{ prefix: 'To', text: '600,00', value: '600,00' },
{ prefix: 'To', text: '800,00', value: '800,00' },
{ text: 'No max', value: 'No max' }
]
}
},
Is there a more elegant and D.R.Y way to do this?
Here is a sandbox what I have so far.
You should bind an object to your v-model on the <price> component.
This way you can pass multiple values to and from your component, without having to use multiple props.
I would also suggest you convert your value in your selects to numbers, so it's easier to use them to compare to your prices.
You've also defined data properties and computed properties in the sandbox (<price> component) with the same name, this is not possible. So you should remove the data properties and stick to the computed ones to handle your data.
Fork of your sandbox with my suggested changes.

ReferenceArrayInput usage with relationships on React Admin

I have followed the doc for the ReferenceArrayInput (https://marmelab.com/react-admin/Inputs.html#common-input-props) but it does not seem to be working with relationship fields.
For example, I have this many-to-many relation for my Users (serialized version) :
Coming from (raw response from my API):
I have setup the ReferenceArrayInput as followed :
<ReferenceArrayInput source="profiles" reference="profiles" >
<SelectArrayInput optionText="label" />
</ReferenceArrayInput>
I think it's making the appropriate calls :
But here is my result :
Any idea what I'm doing wrong ?
Thanks in advance for your help !
On docs, ReferenceArrayInput is said to expect a source prop pointing to an array os ids, array of primitive types, and not array of objects with id. Looks like you are already transforming your raw response from api, so if you could transform a bit more, mapping [{id}] to [id], it could work.
If other parts of your app expects profiles to be an array of objects, just create a new object entry like profilesIds or _profiles.
As gstvg said, ReferenceArrayInput expects an array of primitive type, not array of objects.
If your current record is like below:
{
"id": 1,
"tags": [
{ id: 'programming', name: 'Programming' },
{ id: 'lifestyle', name: 'Lifestyle' }
]
}
And you have a resource /tags, which returns all tags like:
[
{ id: 'programming', name: 'Programming' },
{ id: 'lifestyle', name: 'Lifestyle' },
{ id: 'photography', name: 'Photography' }
]
Then you can do something like this (it will select the tags of current record)
<ReferenceArrayInput
reference="tags"
source="tags"
parse={(value) => value && value.map((v) => ({ id: v }))}
format={(value) => value && value.map((v) => v.id)}
>
<AutocompleteArrayInput />
</ReferenceArrayInput>