Creating a new array from .map() items with certain value - javascript

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>
)
}
})

Related

Changing the value of an object contained within another object and an array

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>

How can I put the data inside the table?

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

I want to set checkbox to checked if the value comes true

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

Loop through an array of objects to update object values and append additional objects

I have a fields array with objects and I'm trying to loop this array:
fields: [
{
name: "seasonId",
type: "select",
label: "Season ID",
placeholder: "Select a season id...",
icon: "id",
value: "",
errors: "",
required: true,
disabled: true,
selectOptions: [],
},
{
name: "callTime",
type: "time",
label: "Scheduling Call Times",
placeholder: "Select a time...",
value: "",
errors: "",
required: true,
disabled: true,
},
];
To update its values AND append additional objects:
Incoming values:
"fieldValues": {
"callTimes": [
"5:45 pm",
"6:15 pm",
"6:30 pm",
"7:00 pm"
],
"selectedSeasonId": "20192020",
"seasonIds": [
"20192020",
"20202021",
"20212022",
]
}
Update field function:
const updateField = (currentField, fieldValues) => {
switch(currentField.name) {
case "seasonId":
return {
...currentField,
selectOptions: fieldValues.seasonIds,
value: fieldValues.selectedSeasonId,
disabled: false
};
case "callTime":
const callTimes = fieldValues.callTimes.map((value, key) => ({
...currentField,
name: key <= 0 ? "callTime" : `callTime-${Date.now()}`,
label: key <= 0 ? "Scheduling Call Times" : "",
value,
required: key <= 0,
disabled: false,
}));
return {
...callTimes
};
}
}
And then invoke the function above like so:
const updatedFields = fields.map(field => updateField(field, event));
However, I'm not getting the desired result.
Actual output:
[
'0': {
disabled: false
errors: ""
icon: "id"
label: "Season ID"
name: "seasonId"
placeholder: "Select a season id..."
required: true
selectOptions: ["20192020", "20202021", "20212022"]
type: "select"
value: "20192020"
},
'1': {
'0': {
disabled: false
errors: ""
label: "Scheduling Call Times"
name: "callTime"
placeholder: "Select a call time..."
required: true
style: {width: "100%"}
type: "time"
value: "5:45 pm"
},
'1': {
disabled: false
errors: ""
label: ""
name: "callTime-1565388886669"
placeholder: "Select a call time..."
required: false
style: {width: "100%"}
type: "time"
value: "6:15 pm"
},
'3': { ... },
'4': { ... }
}
];
Expected output:
[
'0': {
disabled: false
errors: ""
icon: "id"
label: "Season ID"
name: "seasonId"
placeholder: "Select a season id..."
required: true
selectOptions: ["20192020", "20202021", "20212022"]
type: "select"
value: "20192020"
},
'1': {
disabled: false
errors: ""
label: "Scheduling Call Times"
name: "callTime"
placeholder: "Select a call time..."
required: true
style: {width: "100%"}
type: "time"
value: "5:45 pm"
},
'2': {
disabled: false
errors: ""
label: ""
name: "callTime-1565388886669"
placeholder: "Select a call time..."
required: false
style: {width: "100%"}
type: "time"
value: "6:15 pm"
},
'3': { ... },
'4': { ... }
];
Any ideas on how I can update values and append additional objects to my fields array? The callTimes array of string values within the field object is dynamic (can contain 1 string or many), so I can't hard code anything.
const fields = [
{
name: "seasonId",
type: "select",
label: "Season ID",
placeholder: "Select a season id...",
icon: "id",
value: "",
errors: "",
required: true,
disabled: true,
selectOptions: [],
},
{
name: "callTime",
type: "time",
label: "Scheduling Call Times",
placeholder: "Select a time...",
value: "",
errors: "",
required: true,
disabled: true,
},
];
const fieldValues = {
"callTimes": [
"5:45 pm",
"6:15 pm",
"6:30 pm",
"7:00 pm"
],
"selectedSeasonId": "20192020",
"seasonIds": [
"20192020",
"20202021",
"20212022",
]
};
const updateField = (currentField, event) => {
switch(currentField.name) {
case "seasonId":
return {
...currentField,
selectOptions: fieldValues.seasonIds,
value: fieldValues.selectedSeasonId,
disabled: false
};
case "callTime":
const callTimes = fieldValues.callTimes.map((value, key) => ({
...currentField,
name: key <= 0 ? "callTime" : `callTime-${Date.now()}`,
label: key <= 0 ? "Scheduling Call Times" : "",
value,
required: key <= 0,
disabled: false,
}));
return {
...callTimes
};
}
};
const updatedFields = fields.map(field => updateField(field, event));
console.log(updatedFields);
Using reduce instead of map, I believe I am getting the right output:
const updateField = (result, currentField) => {
switch (currentField.name) {
case 'seasonId':
return [
...result,
{
...currentField,
selectOptions: fieldValues.seasonIds,
value: fieldValues.selectedSeasonId,
disabled: false
}
]
case 'callTime':
const callTimes = fieldValues.callTimes.map(...);
return [
...result,
...callTimes
]
}
}
const updatedFields = fields.reduce(updateField, [])
Since your callTime case was returning multiple objects in an array, map wouldn't work well in this case as you need to push/add these objects individually to the "final" array, hence this return:
case 'callTime':
const callTimes = fieldValues.callTimes.map(...);
return [
...result,
...callTimes
]
Also, your callTimes came out to be an array, and you tried to spread its items into an object:
case "callTime":
const callTimes = fieldValues.callTimes.map(...); // array
return {
...callTimes
};
This is why you were getting an unexpected/weird outcome.
Here's a demo with the fix:
Link
Since you asked in the comments how to pass fieldValues to the reducer function since they are being imported from another file, you can do the following:
const updateField = (result, currentField, fieldValues) => {...}
const updatedFields = fields.reduce(
(result, field) => updateField(result, field, fieldValues),
[]
)
Everything else stays the same.
Here's another demo:
Link

Desctructuring object with object arrays

I have this kind of and object:
obj: {
child1: [
{ type, checked, text, ... },
{ type, checked, text, ... },
{ type, checked, text, ... },
],
child2: [
{ type, checked, text, ... },
...
],
...
}
I need almost the same object, but child elements should have objects consisting only of type and checked values. Need my output to be like below example.
OUTPUT:
obj: {
child1: [
{
type: "type",
checked: "checked"
},
{
type: "type",
checked: "checked"
},
{
type: "type",
checked: "checked"
}
],
child2: [
{
type: "type",
checked: "checked"
}
]
}
So far everything I've tried doesn't seem to work.
My last failed attempt:
Object.keys(tabs).forEach(key =>
({
updatedState: {
[key]: (({ documentTypeId, checked }) => ({ documentTypeId, checked }))(tabs[key]),
},
}),
);
You can use Array.reduce() to iterate the object's keys, with an inner Array.map() and destructuring to create new objects from the properties you want to keep:
const type = 'type'
const checked = 'checked'
const text = 'text'
const obj = {
child1: [
{ type, checked, text },
{ type, checked, text },
{ type, checked, text },
],
child2: [
{ type, checked, text },
],
}
const result = Object.keys(obj).reduce((r, k) => {
r[k] = obj[k].map(({ type, checked }) => ({ type, checked }))
return r
}, {})
console.log(result)
You can use a combination of reduce (to iterate through the object keys) and map
(for your children arrays)
const obj = {
child1: [
{ type: 1, checked: true, text: 'aaa'},
{ type: 2, checked: false, text: 'bbb'},
{ type: 3, checked: true, text: 'ccc'}
],
child2: [
{ type: 4, checked: true, text: 'ddd'},
{ type: 5, checked: false, text: 'eee'},
{ type: 6, checked: true, text: 'fff'}
]
};
const result = Object.keys(obj).reduce((acc, key) => {
acc[key] = obj[key].map(child =>
({type: child.type, checked: child.checked}));
return acc;
}, {});
console.log(result);

Categories