I am using the Ant design tree component what my task is am a getting data from the backend in this tree structure and in children data I am getting key checked with the value true and false so I need to set checked if the checked key value is true if come false than not checked so checkbox will be checked by default if children data checked value is true you can also check codeSandBox link below.
const treeData = [
{
title: "First Watchlists",
key: "First Watchlists",
children: [
{ title: " Open Data", key: "Open Data", checked: true },
{
title: "Department of trade ",
key: "Department of trade ",
checked: true
},
{
title: "sanction List",
key: "sanction List",
checked: true
},
{ title: "People's Daily", key: "People's Daily", checked: true },
{
title: "People trades",
key: "People trades",
checked: true
}
]
},
{
title: "Second Watchlists",
key: "Second Watchlists",
children: [
{
title: "Second Service",
key: "Second Service",
checked: true
}
]
},
{
title: "Third Watchlists",
key: "Third Watchlists",
children: [
{
title: "National ",
key: "National ",
checked: false
},
{
title: "Militants List",
key: "Militants List",
checked: false
}
]
},
{
title: "Forth Watchlists",
key: "Forth Watchlists",
children: [
{ title: "FAT", key: "FAT", checked: true },
{ title: "FAC", key: "FAC", checked: false },
{ title: "SC", key: "SC", checked: false },
{
title: "Data Council",
key: "Data Council",
checked: true
},
{
title: " Sanctions List",
key: "Sanctions List",
checked: false
}
]
}
];
const Demo = () => {
const [expandedKeys, setExpandedKeys] = useState(["0-0-0", "0-0-1"]);
const [checkedKeys, setCheckedKeys] = useState(["0-0-0"]);
const [selectedKeys, setSelectedKeys] = useState([]);
const [autoExpandParent, setAutoExpandParent] = useState(true);
const onExpand = (expandedKeysValue) => {
console.log("onExpand", expandedKeysValue); // if not set autoExpandParent to false, if children expanded, parent can not collapse.
// or, you can remove all expanded children keys.
setExpandedKeys(expandedKeysValue);
setAutoExpandParent(false);
};
const onCheck = (checkedKeysValue) => {
console.log("onCheck", checkedKeysValue);
setCheckedKeys(checkedKeysValue);
};
const onSelect = (selectedKeysValue, info) => {
console.log("onSelect", info);
setSelectedKeys(selectedKeysValue);
};
return (
<Tree
checkable
onExpand={onExpand}
expandedKeys={expandedKeys}
autoExpandParent={autoExpandParent}
onCheck={onCheck}
checkedKeys={checkedKeys}
onSelect={onSelect}
selectedKeys={selectedKeys}
treeData={treeData}
/>
);
};
CodeSandBox Link
const buildCheckedKeys = () => {
const checked = [];
treeData.forEach((data) => {
data.children.forEach((item) => {
if (item.checked) {
checked.push(item.key);
}
});
});
return checked;
};
const [checkedKeys, setCheckedKeys] = useState(buildCheckedKeys);
Code can be found here
Related
I have nested JSON object looking like below and this JSON object I have to convert into some particular format which I have given below:
let jsonObj ={"data": {
"cardShop": {
"cardData": {
"cardTitle": "The Platinum Card<sup>®</sup>",
"cardType": "credit-cards",
"dtmProductName": "PlatinumCard",
"viewAllCards": {
"url": "credit-cards/all-cards",
"text": "All Cards"
}
},
"eligibilityChecker": {
"header": "Check your eligibility",
"subHeader": "The Platinum Card®",
"bulletPoints": [
"Only takes a couple of minutes to complete",
"Will not impact your credit rating",
"Allows you to apply with confidence"
]
}
}
}
}
And the above JSON object I have to convert it to the below format with some new properties like key, title, parentId, id, etc..
[
{
id: "cardShop",
key: "cardShop",
title: "cardShop",
selectable: false,
children: [
{
id: "cardData",
path:"cardShopCardData"
key: "cardData",
title: "cardData",
parentId: "cardShop",
selectable: false,
children: [
{
id: "cardTitle",
path :"cardShopcardDatacardTitle"
key: "cardTitle",
title: "cardTitle",
parentId: "cardData",
isLeaf: true,
children: []
},
{
id: "cardType",
key: "cardType",
title: "cardType",
parentId: "cardData",
isLeaf: true,
children: []
},
{
id: "dtmProductName",
key: "dtmProductName",
title: "dtmProductName",
parentId: "cardData",
isLeaf: true,
children: []
},
{
id: "viewAllCards",
key: "viewAllCards",
title: "viewAllCards",
parentId: "cardData",
selectable: false,
children: [
{
id: "url",
key: "url",
title: "url",
parentId: "viewAllCards",
isLeaf: true,
},
{
id: "text",
key: "text",
title: "text",
parentId: "viewAllCards",
isLeaf: true,
}
]
}
]
},
{
id: "eligibilityChecker",
key: "eligibilityChecker",
title: "eligibilityChecker",
parentId: "cardData",
selectable: false,
children: [
{
id: "header",
key: "header",
title: "header",
parentId: "eligibilityChecker",
},
{
id: "subHeader",
key: "subHeader",
title: "subHeader",
parentId: "eligibilityChecker",
},
{
id: "bulletPoints",
key: "bulletPoints",
title: "bulletPoints",
parentId: "eligibilityChecker",
},
{
id: "image",
key: "image",
title: "image",
parentId: "eligibilityChecker",
}
]
}
]
}
];
I have tried below things. For each object I need a parentId.
let prevKey =""
const iterate = (obj) => {
Object.keys(obj).forEach(key => {
if (typeof obj[key] === 'object' && obj[key] !== null) {
let c ={
id:key,
title:key,
selelected:false,
children:[]
};
if(prevKey && Object.keys(output).length === 0){
output ={
children :[]
}
output.children.push(c)
}
else if(prevKey ){
output.children.push(c)
} else{
output = c
}
prevKey = key;
iterate(obj[key])
}
else{
let c ={
id:key,
title:key,
selelected:false,
children:[]
};
output.children[0].children.push(c)
}
})
}
I have tried using recursion but somehow I am not able to get an expected output.
you can do something like this
const transform = data => {
const loop = (data, parent) => Object.entries(data).map(([key, value]) => {
let additional = parent? {
parentId: parent
}:{}
if(typeof value === 'object' && !Array.isArray(value)){
additional = {
...additional,
selectable: false,
children: loop(value, key)
}
}else{
additional.isLeaf = true
}
return {
id: key,
key,
title: key,
...additional
}
})
return loop(data)
}
let jsonObj = {
"data": {
"cardShop": {
"cardData": {
"cardTitle": "The Platinum Card<sup>®</sup>",
"cardType": "credit-cards",
"dtmProductName": "PlatinumCard",
"viewAllCards": {
"url": "credit-cards/all-cards",
"text": "All Cards"
}
},
"eligibilityChecker": {
"header": "Check your eligibility",
"subHeader": "The Platinum Card®",
"bulletPoints": [
"Only takes a couple of minutes to complete",
"Will not impact your credit rating",
"Allows you to apply with confidence"
]
}
}
}
}
console.log(transform(jsonObj.data))
I'm working on a project where I need the values in an array to change depending on if a button is clicked for that specific item. The issue that I'm having is that I need the value of for example 'vegetarian' to change to true when onChangeValue is triggered, but I can't figure out how to change the value of an item in my subCategories and get the whole data array to stay in the same format. Currently, I'm getting:
[{"category": "Diet", "name": "pescatarian", "subCategories": [[Object], [Object], [Object]], "value": true}, {"category": "Daily Exercise in Hours", "subCategories": [{name:'one', value: false },{name:'two', value: false }, {name:'three', value: false }, {name:'four', value: false }]}]
I've tried changing:
return {
...items,
name: item.name,
value: changedValue,
}
to
return {
...items.subCategories,
name: item.name,
value: changedValue,
}
, but that just gives me:
[{"0": {"name": "pescatarian", "value": false}, "1": {"name": "vegan", "value": false}, "2": {"name": "vegetarian", "value": false}, "name": "pescatarian", "value": true}, {"category": "Daily Exercise in Hours", "subCategories": [{name:'one', value: false },{name:'two', value: false }, {name:'three', value: false }, {name:'four', value: false }]}]
I've tried playing around with this a couple of other way, but they gave worse results. Does anyone know how to do this? I would really appreciate any help or advice. Thank you!
Data:
const [data, setData] = useState([
{
category: 'Diet',
subCategories: [
{name:'pescatarian', value: false },
{name:'vegan', value: false },
{name:'vegetarian', value: false }
],
}, {
category: 'Daily Exercise in Hours',
subCategories: [{name:'one', value: false },{name:'two', value: false }, {name:'three', value: false }, {name:'four', value: false }],
},
])
onChangeValue()
const onChangeValue = (item, changedValue) => {
const newData = data.map(items => {
if (items.subCategories.some(x => x.name === item.name)) {
return {
...items,
name: item.name,
value: changedValue,
}
}
return items
})
setData(newData);
}
Array that I need:
[{"category": "Diet", "subCategories": [{name: "pescatarian",value: false},{name:"vegan", value: false },{name:"vegetarian", value: true }], {"category": "Daily Exercise in Hours", "subCategories": [{name:'one', value: false },{name:'two', value: false }, {name:'three', value: false }, {name:'four', value: false }]}]
I have assumed that array you need to change is just the first index, than I think you just need to map the first index.
const onChangeValue = (item, changedValue) => {
const newSub = data[0].subCategories.map(subCat => {
if (subCat.name === item.name) {
return {
...subCat,
value: changedValue,
}
}
return subCat
})
const newData = data
newData[0].subCategories = newSub
setData(newData)
}
Since you want to change a property that is in an array that is inside another array, you can nest .map() calls, like:
function App() {
const [data, setData] = React.useState([
{
category: 'Diet',
subCategories: [
{name:'pescatarian', value: false },
{name:'vegan', value: false },
{name:'vegetarian', value: false }
],
}, {
category: 'Daily Exercise in Hours',
subCategories: [{name:'one', value: false },{name:'two', value: false }, {name:'three', value: false }, {name:'four', value: false }],
},
])
const onChangeValue = (item, changedValue) => {
const newData = data.map(items => {
return {
...items,
subCategories: items.subCategories.map(x => (x.name === item.name ? { ...x, value: changedValue } : x)),
}
})
setData(newData);
}
React.useEffect(() => onChangeValue({ name: 'pescatarian' }, true), []);
return (
<pre>{JSON.stringify(data, null, ' ')}</pre>
);
}
const root = ReactDOM.createRoot(document.getElementById('app'));
root.render(<App />);
<script src="https://unpkg.com/react#18/umd/react.development.js" crossorigin="anonymous"></script>
<script src="https://unpkg.com/react-dom#18/umd/react-dom.development.js"></script>
<div id="app"></div>
I have the following JSON structure:
const sections = [
{
title: "section one",
expanded: false,
feelings: [
{
title: "Joyful",
selected: true,
},
{
title: "Happy",
selected: false,
},
{
title: "Ecstatic",
selected: true,
},
]
},
{
title: "section two",
expanded: false,
feelings: [
{
title: "Angry",
selected: true,
},
{
title: "Mad",
selected: false,
},
]
},
]
I want to filter all feelings that are selected in an array of their own disregarding their section. So the expected outcome should look like this:
[
{
"title": "Joyful",
"selected": true
},
{
"title": "Ecstatic",
"selected": true
},
{
"title": "Angry",
"selected": true
}
]
I tried the following:
const selectedFeelings = feelings.map((feeling) => {
return feeling.sectionFeelings.filter((sectionFeeling) => {
return sectionFeeling.selected === true;
});
});
But this returns them in separate arrays:
[
[
{
"title": "Joyful",
"selected": true
},
{
"title": "Ecstatic",
"selected": true
}
],
[
{
"title": "Angry",
"selected": true
},
],
]
You could use Array.flatMap() along with Array.filter() to return the desired result:
const sections = [ { title: "section one", expanded: false, feelings: [ { title: "Joyful", selected: true, }, { title: "Happy", selected: false, }, { title: "Ecstatic", selected: true, }, ] }, { title: "section two", expanded: false, feelings: [ { title: "Angry", selected: true, }, { title: "Mad", selected: false, }, ] }, ]
const selectedFeelings = sections.flatMap((section) => {
return section.feelings.filter(({ selected }) => selected);
});
console.log(selectedFeelings)
.as-console-wrapper { max-height: 100% !important; }
You could also use Array.reduce() to get the same result:
const sections = [ { title: "section one", expanded: false, feelings: [ { title: "Joyful", selected: true, }, { title: "Happy", selected: false, }, { title: "Ecstatic", selected: true, }, ] }, { title: "section two", expanded: false, feelings: [ { title: "Angry", selected: true, }, { title: "Mad", selected: false, }, ] }, ]
const selectedFeelings = sections.reduce((acc, {feelings}) => {
return [...acc, ...feelings.filter(({ selected }) => selected)];
}, []);
console.log(selectedFeelings)
.as-console-wrapper { max-height: 100% !important; }
You can flatten the returned array once you filter it
const selectedFeelings = feelings.map((feeling) => {
return feeling.sectionFeelings.filter((sectionFeeling) => {
return sectionFeeling.selected === true;
});
}).flat(1);
this is using ES6
const sections = [
{
title: "section one",
expanded: false,
feelings: [
{
title: "Joyful",
selected: true,
},
{
title: "Happy",
selected: false,
},
{
title: "Ecstatic",
selected: true,
},
]
},
{
title: "section two",
expanded: false,
feelings: [
{
title: "Angry",
selected: true,
},
{
title: "Mad",
selected: false,
},
]
},
];
const newArr = sections.map(({ feelings, ...rest }) => {
return rest;
});
console.log(newArr);
I am using mui-datatables. I can already retrieve the data correctly. However, I am quite lost on how to display the data address, ID, and name, and date only in the table.
codesandbox link :https://codesandbox.io/s/infallible-feistel-bki5h?file=/src/App.js
This is the data in a JSON format.
[
{
name: "Sample Name",
items: {
id: "34234242",
selectedItem: "Item",
date: { seconds: 1636905600, nanoseconds: 0 },
item1: true,
item2: false,
},
address: "Ayala",
email: "sample email",
phone: "823840820943",
},
];
Below are the codes.
const filter = users.filter((d) => d?.items?.item2 == false);
const filtered = selection.filter((f) => f?.items?.date <= new Date());
return (
<div>
{" "}
<MUIDataTable title={"List"} columns={columns} data={filtered} />
</div>
);
};
export default UserTable;
You need columns options where you include address, ID, name, and date. You can also hide column (using display: false) that are included into your column list. please the below example and you can check MUI Datatable documentation too.
import MUIDataTable from "mui-datatables";
const columns = [
{
name: "name",
label: "Name",
options: {
filter: true,
sort: true,
}
},
{
name: "company",
label: "Company",
options: {
filter: true,
sort: false,
}
},
{
name: "city",
label: "City",
options: {
filter: true,
sort: false,
display: false,
}
},
{
name: "state",
label: "State",
options: {
filter: true,
sort: false,
}
},
];
const data = [
{ name: "Joe James", company: "Test Corp", city: "Yonkers", state: "NY" },
{ name: "John Walsh", company: "Test Corp", city: "Hartford", state: "CT" },
{ name: "Bob Herm", company: "Test Corp", city: "Tampa", state: "FL" },
{ name: "James Houston", company: "Test Corp", city: "Dallas", state: "TX" },
];
const options = {
filterType: 'checkbox',
};
<MUIDataTable
title={"Employee List"}
data={data}
columns={columns}
options={options}
/>
Update based on your comment
You need to consider two things:
Need to use customBodyRender to show complex json data like items.SelectedItem
{
name: "items",
label: "Item",
options: {
filter: true,
sort: true,
customBodyRender: (value, tableMeta, updateValue) => {
console.log(value, tableMeta, updateValue, "test");
return value.selectedItem;
}
}
}
Need to use setRowProps to show background color of selected row based on condition. you need options to use setRowProps
const options = {
filter: true,
filterType: "dropdown",
fixedSelectColumn: false,
rowHover: false,
setRowProps: (row, dataIndex, rowIndex) => {
return {
style: row[1] === "Item" ? { backgroundColor: "skyblue" } : {}
};
}
};
Here is the complete example:
Updated Example in Codesandbox
In a React app, I have an array of key value pairs. Each pair corresponds to a checkbox, so when the checkbox is checked, the value of that key changes to either true or false. The data that i am pulling from is structured like:
filters: {
categories: [
{
name: "Books",
slug: "books",
selected: 0,
data: [
{ checked: false, value: "Fiction", label: "Fiction" },
{ checked: false, value: "NonFiction", label: "NonFiction" },
{ checked: false, value: "Biography", label: "Biography" },
],
},
{
name: "Movies",
slug: "movies",
selected: 0,
data: [
{ checked: false, value: "SciFi", label: "SciFi" },
{ checked: false, value: "Comedy", label: "Comedy" },
{ checked: false, value: "Romance", label: "Romance" },
],
},
{
name: "Music",
slug: "music",
selected: 0,
data: [
{ checked: false, value: "Pop", label: "Pop" },
{ checked: false, value: "Rock", label: "Rock" },
{ checked: false, value: "Alt", label: "Alt" },
],
},
],
selected: 0,
},
And I am displaying a simple list on the front-end like:
{state.theme.filters.categories.map((filter, id) => {
return (
<>
{filter.data.map((item) => {
return (
<p>{item.value}: {item.checked === true ? <span>True</span> : <span>False</span>}</p>
)
})}
</>
)
})}
What I am trying to do is create a new array that will automatically update and return only items that are checked true.
Is this something that is possible?
Yes, it is posible.
You need to filter the array.
{state.theme.filters.categories.map((filter, id) => {
return (
<>
{filter.data.filter(item => item.checked).map((item) => {
return (
<p>{item.value}: {item.checked === true ? <span>True</span> : <span>False</span>}</p>
)
})}
</>
)
})}
I think you simply want to check the checked value before returning, and not return otherwise. Something like this:
filter.data.map((item) => {
if (item.checked === true) {
return (
<p>{item.value}</p>
)
}
})