Update array of objects based on the object passed - javascript

I have an array of objects that has the following format,
const options = [
{ key: 1, text: "Name", value: "name", icon: "sort" },
{ key: 2, text: "Time", value: "time", icon: "sort" },
{ key: 3, text: "Type", value: "type", icon: "sort" }
];
Now based on the input passed which of format {fieldName,order} I have to modify the array. Basically order will take two values "asc" or "desc" and the fieldName will take any of the values in the value property of options array.
For Example : { fieldName: "name", order : "asc"} or { fieldName: "type", order: "desc"}
Now basically based this order , I have modify the icon field of the source array for that field.
If order is asc, then change the icon property for that field to sort up .If its order is desc, then change the icon property for that field to sort down
Example
1) sortBy: { fielName: "name", order:"asc"}
//Output
[
{ key: 1, text: "Name", value: "name", icon: "sort up" },
{ key: 2, text: "Time", value: "time", icon: "sort" },
{ key: 3, text: "Type", value: "type", icon: "sort" }
];
2) sortBy: { fielName: "type", order:"desc"}
//Output
[
{ key: 1, text: "Name", value: "name", icon: "sort" },
{ key: 2, text: "Time", value: "time", icon: "sort" },
{ key: 3, text: "Type", value: "type", icon: "sort down"}
];
It should update icon only of the field passed to it, and rest fields icon should be set to "sort"
This is what I tried
const options = [
{ key: 1, text: "Name", value: "name", icon: "sort" },
{ key: 2, text: "Time", value: "time", icon: "sort" },
{ key: 3, text: "Type", value: "type", icon: "sort" }
];
function updateArray(obj)
{
const newArr = options.map(item => {
if(item.name === obj.fieldName) {
return {...item, icon: obj.order === "desc" ? "sort-desc" :"sort-asc" };
}
return {...item};
});
return newArr;
}

Try this
const options = [
{ key: 1, text: "Name", value: "name", icon: "sort" },
{ key: 2, text: "Time", value: "time", icon: "sort" },
{ key: 3, text: "Type", value: "type", icon: "sort" }
];
function sorta(op,options){
field =op.fielName
newarray=[]
options.forEach(o=>{
if(o.value==field){
op.order=="asc"?f="up":f="down"
o.icon="sort-"+f
newarray.push(o)
}
else newarray.push(o)
})
return newarray
}
console.log(sorta({ fielName: "name", order:"asc"},options ))

Your function works, but you are trying to access a non-existent property.
I believe it should be:
if(item.value === obj.fieldName) {
...
}
Demo:
const options = [
{ key: 1, text: "Name", value: "name", icon: "sort" },
{ key: 2, text: "Time", value: "time", icon: "sort" },
{ key: 3, text: "Type", value: "type", icon: "sort" }
];
function updateArray(obj)
{
const newArr = options.map(item => {
if(item.value === obj.fieldName) {
return {...item, icon: obj.order === "desc" ? "sort-desc" :"sort-asc" };
}
return {...item};
});
return newArr;
};
console.log(updateArray({fieldName: 'type', order: 'desc'}));
console.log(updateArray({fieldName: 'time', order: 'asc'}));
console.log(updateArray({fieldName: 'name', order: 'desc'}));

Related

Antd Tree, : how to Disable checking child by default

I working on a react project using Antd and I want to be able to disable cheking childs of my Tree component, so I can check only parent.This is my code
I found that I can add checkable : false to my child but I must create a function that render me a new TreeData that I can use instead of my normal data so I've tried this :
const TreeData = (data) => {
data.map((category) => {
category.children.map((family) => {
family.children.map((table) => {
table.checkable = false;
});
});
});
};
But it return undefined when i'm console.log the data received..
So my question is : how to switch from this :
const treeData = [
{
title: "0-0",
key: "0-0",
children: [
{
title: "0-0-0",
key: "0-0-0",
children: [
{
title: "0-0-0-0",
key: "0-0-0-0"
},
{
title: "0-0-0-1",
key: "0-0-0-1"
},
{
title: "0-0-0-2",
key: "0-0-0-2"
}
]
},
{
title: "0-0-1",
key: "0-0-1",
children: [
{
title: "0-0-1-0",
key: "0-0-1-0"
},
{
title: "0-0-1-1",
key: "0-0-1-1"
},
{
title: "0-0-1-2",
key: "0-0-1-2"
}
]
},
{
title: "0-0-2",
key: "0-0-2"
}
]
},
{
title: "0-1",
key: "0-1",
children: [
{
title: "0-1-0-0",
key: "0-1-0-0"
},
{
title: "0-1-0-1",
key: "0-1-0-1"
},
{
title: "0-1-0-2",
key: "0-1-0-2"
}
]
},
{
title: "0-2",
key: "0-2"
}
];
To this :
const treeData = [
{
title: "0-0",
key: "0-0",
children: [
{
checkable: false,
title: "0-0-0",
key: "0-0-0",
children: [
{
title: "0-0-0-0",
key: "0-0-0-0"
},
{
title: "0-0-0-1",
key: "0-0-0-1"
},
{
title: "0-0-0-2",
key: "0-0-0-2"
}
]
},
{
checkable: false,
title: "0-0-1",
key: "0-0-1",
children: [
{
title: "0-0-1-0",
key: "0-0-1-0"
},
{
title: "0-0-1-1",
key: "0-0-1-1"
},
{
title: "0-0-1-2",
key: "0-0-1-2"
}
]
},
{
checkable: false,
title: "0-0-2",
key: "0-0-2"
}
]
},
{
title: "0-1",
key: "0-1",
children: [
{
checkable: false,
title: "0-1-0-0",
key: "0-1-0-0"
},
{
checkable: false,
title: "0-1-0-1",
key: "0-1-0-1"
},
{
checkable: false,
title: "0-1-0-2",
key: "0-1-0-2"
}
]
},
{
title: "0-2",
key: "0-2"
}
];
Without hardchanging the first data of my Tree.
Thank you
This may be one possible implementation to set checkable as false for the specific nodes described in this question:
const makeUnCheckable = dataArr => (
dataArr.map(
obj => ({
...obj,
children: obj?.children?.map(cObj => ({
...cObj,
checkable: false
}))
})
)
);
return (
<Tree
checkable
onExpand={onExpand}
expandedKeys={expandedKeys}
autoExpandParent={autoExpandParent}
onCheck={onCheck}
checkedKeys={checkedKeys}
onSelect={onSelect}
selectedKeys={selectedKeys}
treeData={makeUnCheckable(treeData)}
/>
);
This is the result displayed on Codesandbox:
NOTES:
The elements showing as checked are clicked manually.
There is no check option for nodes 0-0-0, 0-0-1, 0-0-2, 0-1-0-0, 0-1-0-1, 0-1-0-2 - which is the expected objective defined in the question under To this
EDITED:
On perusing this previous question it seems like OP requires something like this:
(A tree where leaf nodes are uncheckable)
This may be achieved by a recursive method - something like this:
(Changes are present in: Lines 100 to 106. And line 118.)
EDITED - 2
Update based on comments below.
In order to identify the children for any given parent/key, something like the below may be useful:
Two methods are here. One is findKey which is recursive and gets the object which has a particular key (say 0-0-1). The other is to check if the object with the key has any children and if yes, return the children array.

Map the object using javascript and get expected structure object

I want to map below mentioned object...
Input object:
const rules = {
public: [
{ label: 'View', value: 'View' },
{ label: 'Create', value: 'Create' },
{ label: 'Delete', value: 'Delete' },
{ label: 'Update', value: 'Update' },
{ label: 'ChangeLayout', value: 'ChangeLayout' }
],
user: [
{ label: 'View', value: 'View' },
{ label: 'Create', value: 'Create' },
{ label: 'Delete', value: 'Delete' },
{ label: 'Update', value: 'Update' },
{ label: 'ChangeLayout', value: 'ChangeLayout' }
]
};
Expected output is:
const result = {
Public: { "View": true, "Create": false, "Delete": false, "Update": false, "ChangeLayout": false },
User: { "View": true, "Create": true, "Delete": true, "Update": true, "ChangeLayout": true }
};
Actually i try some method but cant getting expected output
Thanks to advance please help anyone...
Please try to use below code
const rules = [
{ label: 'View', value: 'View' },
{ label: 'Create', value: 'Create' },
{ label: 'Delete', value: 'Delete' },
{ label: 'Update', value: 'Update' }
];
let outPut = {};
rules.forEach(item => {
outPut[item.value] = true;
})
console.log(outPut);
Your callback function is just returning a string, so map() is creating an array of strings, not an object.
The callback function should return an array containing the key and value. Then you can use Object.fromEntries() to turn that into the desired object.
const rules = {
public: [
{ label: 'View', value: 'View' },
{ label: 'Create', value: 'Create' },
{ label: 'Delete', value: 'Delete' },
{ label: 'Update', value: 'Update' },
{ label: 'ChangeLayout', value: 'ChangeLayout' }
],
user: [
{ label: 'View', value: 'View' },
{ label: 'Create', value: 'Create' },
{ label: 'Delete', value: 'Delete' },
{ label: 'Update', value: 'Update' },
{ label: 'ChangeLayout', value: 'ChangeLayout' }
]
};
const test = Object.fromEntries(Object.entries(rules).map(
([owner, rules]) => [owner, Object.fromEntries(
rules.map(rule => [rule.value, true]))]));
console.log(test);
To create a single object from your array, you can use a reduce operation, assigning the resulting key name via computed property names.
const rules = [{"label":"View","value":"View"},{"label":"Create","value":"Create"},{"label":"Delete","value":"Delete"},{"label":"Update","value":"Update"}]
const keyFrom = "value"
const t0 = performance.now()
const result = rules.reduce((obj, rule) => ({
...obj,
[rule[keyFrom]]: true
}), {})
const t1 = performance.now()
console.log(result)
console.log(`Operation took ${t1 - t0}ms`)
I wasn't sure which property should provide the key name in your final object so I made it configurable via the keyFrom variable.

How to update nested object array in js?

I need to modify component state which has inner array objects. There is no problem with modifying object array but I'd like to update inner object array value which has action format. It doesn't update the action value as "No Action Needed".
What's the wrong with that map() functions?
Thanks in advance.
let example_response = {
data: [
{
details: [
{
format: "date",
value: "2020-04-29T15:03:44.871Z",
title: "Date"
},
{
format: "action",
value: "-",
title: "Action"
}
],
id: 13409,
isSelected:true
}, {
details: [
{
format: "date",
value: "2019-04-29T15:03:44.871Z",
title: "Date"
},
{
format: "action",
value: "-",
title: "Action"
}
],
id: 13409,
isSelected:false
}
]
};
const newList = example_response.data.map((item) => {
if (item.isSelected) {
item.details.map((elem) => {
if (elem.format === "action") {
const updatedElem = {
...elem,
value: "No Action Needed"
};
return updatedElem;
}
});
}
return item;
});
console.log(newList);
I found 2 problems:
You are not modifying item.details (you are just mapping it).
You only return updatedElem when elem.format === "action" but you're returning anything otherwise
Try
let example_response = {
data: [{
details: [{
format: "date",
value: "2020-04-29T15:03:44.871Z",
title: "Date"
},
{
format: "action",
value: "-",
title: "Action"
}
],
id: 13409,
isSelected: true
}, {
details: [{
format: "date",
value: "2019-04-29T15:03:44.871Z",
title: "Date"
},
{
format: "action",
value: "-",
title: "Action"
}
],
id: 13409,
isSelected: false
}]
};
const newList = example_response.data.map((item) => {
if (item.isSelected) {
item.details = item.details.map((elem) => {
if (elem.format === "action") {
elem.value = "No Action Needed";
}
return elem;
});
}
return item;
});
console.log(newList);
Since you're already creating a new array with the top level map method, you can use forEach and assign the value.
let example_response = {
data: [
{
details: [
{
format: "date",
value: "2020-04-29T15:03:44.871Z",
title: "Date"
},
{
format: "action",
value: "-",
title: "Action"
}
],
id: 13409,
isSelected:true
}, {
details: [
{
format: "date",
value: "2019-04-29T15:03:44.871Z",
title: "Date"
},
{
format: "action",
value: "-",
title: "Action"
}
],
id: 13409,
isSelected:false
}
]
};
const newList = example_response.data.map((item) => {
if (item.isSelected) {
item.details.forEach((elem) => {
if (elem.format === "action") {
elem.value = "No Action Needed";
}
});
}
return item;
});
console.log(newList);
let example_response = {
data: [{
details: [{
format: "date",
value: "2020-04-29T15:03:44.871Z",
title: "Date"
},
{
format: "action",
value: "-",
title: "Action"
}
],
id: 13409,
isSelected: true
},
{
details: [{
format: "date",
value: "2019-04-29T15:03:44.871Z",
title: "Date"
},
{
format: "action",
value: "-",
title: "Action"
}
],
id: 13409,
isSelected: false
}
]
};
const newList = example_response.data.map(item => item.isSelected
? item.details.map(elem => elem.format === "action"
? ({ ...elem, value: "No Action Needed" })
: elem)
: item.details);
console.log(newList);
Your code does not return a modified item, it just maps over the details when the item is selected. Make sure you are returning something in else clauses too. Here's an example using shorthand notation:
const elementUpdater = (element) => element.format === 'action' ? {...element, value: 'No action needed'} : element
const itemDetailsUpdater = (item) => item.isSelected ? item.details.map(elementUpdater) : item
example_response.data.map(itemDetailsUpdater)
Which yields:
[
[
{
"format": "date",
"value": "2020-04-29T15:03:44.871Z",
"title": "Date"
},
{
"format": "action",
"value": "No action needed",
"title": "Action"
}
],
{
"details": [
{
"format": "date",
"value": "2019-04-29T15:03:44.871Z",
"title": "Date"
},
{
"format": "action",
"value": "-",
"title": "Action"
}
],
"id": 13409,
"isSelected": false
}
]

merge array object with pure JavaScript

I need to merge two arrays with objects inside with JavaScript.
How can this be done?
I am currently using this code, but it is not for me:
var array_merge = [];
var array_one = [
{
label: "label",
value: "value",
},
{
label: "label",
value: "value",
},
];
array_merge.push(array_one);
var array_two = [
{
label: "label",
value: "value",
},
{
label: "label",
value: "value",
},
];
array_merge.push(array_two);
How can I join them so that the result is the following?
var array_merge = [
{
label: "label",
value: "value",
},
{
label: "label",
value: "value",
},
{
label: "label",
value: "value",
},
{
label: "label",
value: "value",
},
];
Thanks.
You can use the concat method to merge arrays
The concat() method is used to merge two or more arrays. This method does not change the existing arrays, but instead returns a new array.
const array_one = [
{
label: "label",
value: "value",
},
{
label: "label",
value: "value",
},
];
const array_two = [
{
label: "label",
value: "value",
},
{
label: "label",
value: "value",
},
];
const array_merge = array_one.concat(array_two);
console.log(array_merge)

How to get and link nested value to field passing columns to Material Table

I'm trying to create a table and I have nested data like this:
[{
id: 24,
name: "DANIEL TSUTOMU OBARA",
number: "134",
phone: "11111111111",
rg: "4034092666",
EmployeeStatus: {
createdAt: "2019-08-07T14:38:52.576Z"
description: "Documentos rejeitados"
id: 3
updatedAt: "2019-08-07T14:38:52.576Z"
},
Sector: {
id: 2,
name: "Controladoria"
}
}]
And have this structure columns table:
columns: [
{ title: "Nome", field: "name" },
{ title: "CPF", field: "cpf" },
{ title: "Função", field: "FunctionId", lookup: {} },
{
title: "Setor",
field: "SectorId",
lookup: {}
},
{
title: "Status",
field: "EmployeeStatus", <------- I want to get description here
editable: "never"
}
],
Then, I need to pass these columns into my Material-table like this:
<MaterialTable
columns={state.columns}
data={state.data}
title=""
icons={tableIcons}
editable={{
onRowAdd: newData => createInstructor(newData),
onRowUpdate: async (newData, oldData) =>
updateInstructor(newData, oldData),
onRowDelete: oldData => deleteInstructor(oldData)
}}
/>
So, how I can do that access nested data into column field?
Thanks!
Please find the below solution.
I am expecting the data to have other objects too, so finding the first object with the key available.
let data = [{
id: 24,
name: "DANIEL TSUTOMU OBARA",
number: "134",
phone: "11111111111",
rg: "4034092666",
EmployeeStatus: {
createdAt: "2019-08-07T14:38:52.576Z",
description: "Documentos rejeitados",
id: 3,
updatedAt: "2019-08-07T14:38:52.576Z"
},
Sector: {
id: 2,
name: "Controladoria"
}
}]
let columns = [
{ title: "Nome", field: "name" },
{ title: "CPF", field: "cpf" },
{ title: "Função", field: "FunctionId", lookup: {} },
{
title: "Setor",
field: "SectorId",
lookup: {}
},
{
title: "Status",
field: "EmployeeStatus",
editable: "never"
}
];
let columnToUpdate = columns.find(obj => obj.title==="Status"); //find the column in columns array
let desc = data.find(obj => Object.keys(obj).includes('EmployeeStatus')).EmployeeStatus.description; // get description
columnToUpdate.field = desc; // mutate the object
console.log(columns);
I just decided to use lookup functionality and solve in this way for now.
const [state, setState] = useState({
columns: [
{ title: "ID", field: "id", editable: "never" },
{ title: "Nome", field: "name" },
{ title: "CPF", field: "cpf" },
{ title: "Função", field: "FunctionId", lookup: {} }, // 3
{
title: "Setor",
field: "SectorId",
lookup: {}
}, // 4
{
title: "Status",
field: "EmployeeStatusId",
lookup: {},
editable: "never"
}, // 5
]});
....
await api
.get(`/employee-status`)
.then(result => {
status = formatSectors(state, result, 5);
})
.....
const formatSectors = (state, result, position) => {
let columns = state.columns;
const indexColumnSector = 4;
columns[position].lookup = result.data.rows.reduce(
(accumulator, currentValue) => {
accumulator[currentValue.id] =
position === indexColumnSector
? currentValue.name
: currentValue.description;
return accumulator;
},
{}
);
return columns;
};

Categories

Resources