React Cascading Dropdowns (Dynamic) - javascript

The scenario is as follows: I want to make a reusable cascading dropdown component, however every video/article that I've seen on the topic just uses hard coded dependent dropdowns such as: Country => State => City.
However, for my situation it will not always be the same dependencies. How can I support custom dependency for cascading dropdowns?
For a hardcoded example I would do something along the lines of having one useEffect for each of the options, and make the dependant options change when the parent changes.
I have an object example to iterate through of one page I am trying to accomplish this for:
[
{
key: 0,
name: "State",
parentQuestion: null,
inputType: "Dropdown",
},
{
key: 1,
name: "Sublocation",
parentQuestion: "State",
inputType: "Dropdown",
},
{
key: 2,
name: "Operation",
parentQuestion: "Sublocation",
inputType: "Dropdown",
},
{
key: 3,
name: "Installment Number",
parentQuestion: "Operation",
inputType: "Dropdown",
},
{
key: 4,
name: "Upload Directory",
parentQuestion: null,
inputType: "File",
},
{
key: 5,
name: "Download Directory",
parentQuestion: null,
inputType: "Directory",
},
]
Is it possible to accomplish this? Or must I hardcode the logic with different hooks for each page?

You can have the component built passing the array data as props, then iterating over each key on an element of the array, you have to build the selects using map. For the option values list you have to prepare another object such that
optionList={country:[],state:[],city:[]}
You have to maintain an object with selected options, and onchange of the selects you have to modify the object for selected options.
Edit
Also onchange of selects you have to modify the optionList object, reducing the options array, for example
if country is selected 'UK' then on the final object selected you add the value final_object={country:'UK'} and then in optionList you have to reduce the options for corresponding state and city

Related

How to filter data based on populated item's null

I do have object. For example -
{
active: true,
category: { _id: 1212, name: 'something', active: false},
name: "test",
}
My category object came from mongodb populated item. Now when I populated item I filtered it based on active=false. which returned null on category field.
For instance,
{
active: true,
category: null,
name: "test",
}
Now my main focus is to remove this object if category is null.
I did use like this -
match: { category: { $exists: true } },
populate: "category"
but it doesn't work because initially category object exists. But after populate and based on active status it's became null.
So what is the best way to remove this object if category is null.
N.B: I know it will work using aggregate. But I do not use aggregate because the query is too long. I have to change many things if I do aggregate. And populate is multilevel. So it will be a problem.
In your code you are looking for a field that "exists" even though its value is null, the field is there.
You could just search for the null value and it should work.
match: { category: null }

Searching from multiple keys inside object in javascript (reactJS)

i have the the following array of object which indicated all the possible combination of a product
[{id:25,attributes:[{id: 0, name: "Weight", option: "250gr"},{id: 0, name: "Roast", option: "Medium"},{id: 0, name: "Packaging", option: "Card"}
{id:26,attributes:[{id: 0, name: "Weight", option: "500gr"},{id: 0, name: "Roast", option: "Medium"},{id: 0, name: "Packaging", option: "Card"}
{id:27,attributes:[{id: 0, name: "Weight", option: "250gr"},{id: 0, name: "Roast", option: "Light"},{id: 0, name: "Packaging", option: "Card"}
{id:28,attributes:[{id: 0, name: "Weight", option: "250gr"},{id: 0, name: "Roast", option: "Light"},{id: 0, name: "Packaging", option: "Tin"}
]
On the webpage, options are set via select; the select also set a state component as follow:
{Weight:"",Roast:"",Pakaging:""}
with the values from the selected option, for example (assuming only weight and roast are selected):
{Weight:"250gr",Roast:"Light",Packaging:""}
everytime a option is selected i want to narrow down the combination of product (based on the selection) until i finally got only one option available (also the combination are used for dinamically repopulate select, adding or removing available options based on previous selections)
until now i was using something like (inside the function called by onChange on a select):
const result = variations.filter((p) =>
p.attributes.some((c) => c.option === event.target.value)
);
but this way it reduces based on the latest selection, so if i start selecting 250gr it gives me a set of 3 (25,27,28)
then if i select Medium, it give me a set of 2 (25 and 26) filtering only on medium and ignoring Weight
i'm looking to convert my filter, instead that on event.target.value, on the object but i cant find the right method, anyone can help?
You need to persist the selected filters like this:
const [filters, setFitlers] = React.useState({});
const onFilterChange = (e) => {
setFitlers(prevFilters => ({...prevFilters, [e.target.name]: e.target.name})
}
Now you can filter like this:
const result = variations.filter((p) =>
Object.entries(filters).every(([key, value]) => p.attributes[key] === value)
);
Obejct.entries will give you the key and value pairs of the filter object. And with every, you check if all the filters match.
Now you only have to give the input a name to fit your name:
<input name="weight" onChange={onFilterChange} .../>
To remove filters, maybe filter the filter object as well to remove empty strings:
Object.entries(filters).filter(([key,value) => value).every....

How to create tree view inside the dropdown using angular material?

Can anyone tell me, how to create a tree view inside the drop down. The drop down values will be getting from rest api call as json as follows. And subchild may contains one more level of child as well.
I have to do auto suggestion here to perform the filter from parent as well as the child level too.
VehicleList = [
{
parent: "audi",
child: [{
type: 'G-audiA',
subchild: [{
id: 1,
name: 'type audi A1'
}, {
id: 2,
name: 'type audi A2'
}]
}, {
type: 'G-audiB',
subchild: [{
id: 1,
name: 'type audi B1'
}, {
id: 2,
name: 'type audi B2'
}]
}]
}, {
parent: "bmw",
child: [{
type: 'G-bmwA',
subchild: [{
id: 1,
name: 'type bmw A1'
}, {
id: 2,
name: 'type bmw A2'
}]
}, {
type: 'G-bmwB',
subchild: [{
id: 1,
name: 'type bmw B1'
}, {
id: 2,
name: 'type bmw B2'
}]
}]
}]
Anyone help will be appreciated!!!
Based on the first example from the Angular Material Tree docs I managed to build up a drop-down with a tree structure inside like so:
The trick for displaying the tree is to add a disabled/empty option. I used it as a label. The tree is taken from their examples so I did not modify it at all, you can modify the node structure to match your own.
In order to display the selected items in the label of the drop-down, you can create a method that will return the selected items a string as their SelectionModel object has the selected property which would return all selected nodes.
/** The selection for checklist */
checklistSelection = new SelectionModel<TodoItemFlatNode>(
true /* multiple */
);
And in order to get the selected items from the tree:
return this.checklistSelection.selected.map(s => s.item).join(",");
For the filtering part I think you can look over this answer.
Hope this is helpful!
Stackblitz
Edit: If you select a child the parent gets selected too and added in the SelectionModel even if all its children are not selected. If you don't want this behaviour comment on the function descendantsPartiallySelected. This will not check the checkbox and so parents will not be added in SelectionModel unless all children are selected

React: Handling an onChange within mapping render

I have created a matrix/table using material ui and have also used a button toggle to select a value.
The table is a matrix where a member can see what their current membership is, and they can choose from other membership types based on age... seniors, juniors, infants.
https://codesandbox.io/s/64j65yrxpw
The demo above will give more clarity. The issue is that when I select an option of yes, no or maybe - all options across all people are selected rather than just that person in that row and across all membership types - (click an option and you will see the problem).
The below is what feeds the table:
const selected = [
{ personId: "0001657", fullName: "Joe Bloggs", seniorStatus: "Yes" },
{ personId: "0001666", fullName: "John Doe", seniorStatus: "No" }
];
and ideally will want something like this returned based on selections:
const newlySelected = [
{ personId: "0001657", fullName: "Joe Bloggs", seniorStatus: "Yes", juniors: "maybe" },
{ personId: "0001666", fullName: "John Doe", seniorStatus: "No", juniors: "no", infants: "yes" },
];
I appreciate that there are two issues here... the toggle not behaving individually and the return of desired json - any help would be awesome. thanks
You have a "too simple" state.
state = {
alignment: "left",
formats: ["bold"]
};
Your state.alignment used by all buttons. If you want to keep it in the form of single component you need to make it 2D array:
[
['<#1 btn value>', '<#2 btn value', ...],
[..., ..., ...]
]
Then when you call setState you need to change the relevant item in the 2D array based on the action location. You have to indexes, one of the row, one of the cell, you can use them.
UPDATE
New state - 2D array
value: [
["no", "no", "no"],
["no", "no", "no"]
]
New ToggleButtonGroup - using rowIdx and cellIdx to have the right position in the 2D array
<ToggleButtonGroup
className={classes.toggleButtonGroup}
value={value[rowIdx][cellIdx]}
exclusive
onChange={(event, val) => this.handleValue(event, val, rowIdx, cellIdx)}
>
New handleValue - using the rowIdx, cellIdx to change the value in the right position.
handleValue = (event, val, rowIdx, cellIdx) => {
const newValue = [...this.state.value]
newValue[rowIdx][cellIdx] = val
this.setState({
value: newValue,
})
}

How to determine binding type for items in a sap.m.Select?

When using a sap.m.Input, I can configure the element like in the example below, in order to set the type of the item that is binded to the Input:
<mvc:View>
<Input value="{
path:'/company/revenue',
type: 'sap.ui.model.type.Float'
}"/>
</mvc:View>
this way, when I retrieve the property inside '/company/revenue', its type will always be a JavaScript number. However, is it possible to apply a similar "typing" to a sap.m.Select? The property "selectedKey" inside a sap.m.Select always returns a JavaScript String, but I would like to type it to a number like I did with the sap.m.Input above. How can I do it? Thanks in advance!
Yes, you can do that. It's just a normal property binding.
But beware that the keys of your items inside the Select control have to be compatible with the Float type. The sap.ui.model.type.Float without any formatOptions generates locale dependant strings. So in germany f.e. you get a , as decimal separator and in the US it would be ..
A good idea would be to use a aggregation binding to create the items and configure the keys of the items with the same type as the selectedKey property of your select. See example on JSbin.
<Select
selectedKey="{path:'/selectedKey',type: 'sap.ui.model.type.Float'}"
items="{/items}">
<c:ListItem
key="{path: 'key', type: 'sap.ui.model.type.Float'}"
text="{text}"/>
</Select>
onInit:function(){
var data = {
selectedKey:3,
items: [
{ key: -1, text: "Item 1" },
{ key: 1.234, text: "Item 2" },
{ key: 3, text: "Item 3" },
{ key: 1234, text: "Item 4" }
]
};
var model = new sap.ui.model.json.JSONModel(data);
this.getView().setModel(model);
}

Categories

Resources