I have two array like this:
let arr1 = [
{id: "1", icon: Images.icon.food, checkable: false, text: 'Dine-in', description: "coupon for dine in"},
{id: "2", icon: Images.icon.delivery, checkable: false, text: 'Delivery', description: "coupon for delivery"},
{id: "3", icon: Images.icon.collection, checkable: false, text: 'Collection', description: "coupon for collection"},
]
let arr2 = [
{description: "Dine in Service", id: "13", isActive: false, name: "Dine In", serviceDetail: null, serviceId: "1", slug: "dine-in"},
{description: "Delivery Service", id: "14", isActive: true, name: "Delivery", serviceDetail: null, serviceId: "2", slug:"delivery"},
{description: "Collection Service", id: "15", isActive: true, name: "Collection", serviceDetail: null, serviceId: "3", slug: "collection"}
]
How to compare id of arr1 equa to serviceId of arr2, and then set value checkable in arr1 equa to isActice in arr2
This is result I want to be:
result = [
{id: "1", icon: Images.icon.food, checkable: false, text: 'Dine-in', description: "coupon for dine in"},
{id: "2", icon: Images.icon.delivery, checkable: true, text: 'Delivery', description: "coupon for delivery"},
{id: "3", icon: Images.icon.collection, checkable: true, text: 'Collection', description: "coupon for collection"},
]
Means result like arr1 but change checkable equa to isActive of arr2.
Thank you.
Use can simply use find and use an arrow function to define the comparision expression. And then you can simply do the attribution directly
let arr1 = [
{id: "1", icon: 'food', checkable: false, text: 'Dine-in', description: "coupon for dine in"},
{id: "2", icon: 'delivery', checkable: false, text: 'Delivery', description: "coupon for delivery"},
{id: "3", icon: 'collection', checkable: false, text: 'Collection', description: "coupon for collection"},
];
let arr2 = [
{description: "Dine in Service", id: "13", isActive: false, name: "Dine In", serviceDetail: null, serviceId: "1", slug: "dine-in"},
{description: "Delivery Service", id: "14", isActive: true, name: "Delivery", serviceDetail: null, serviceId: "2", slug:"delivery"},
{description: "Collection Service", id: "15", isActive: true, name: "Collection", serviceDetail: null, serviceId: "3", slug: "collection"}
];
for(let i = 0; i < arr1.length; i++){
arr1[i].checkable = arr2.find(x => x.serviceId == arr1[i].id).isActive;
console.log(arr1[i]);
}
If you prefer a one line forEach
arr1.forEach((array1) => array1.checkable = arr2.find(x => x.serviceId == array1.id).isActive );
You could collect all active states in an object and map new object with the state.
let arr1 = [{ id: "1", icon: 'Images.icon.food', checkable: false, text: 'Dine-in', description: "coupon for dine in" }, { id: "2", icon: 'Images.icon.delivery', checkable: false, text: 'Delivery', description: "coupon for delivery" }, { id: "3", icon: 'Images.icon.collection', checkable: false, text: 'Collection', description: "coupon for collection" }],
arr2 = [{ description: "Dine in Service", id: "13", isActive: false, name: "Dine In", serviceDetail: null, serviceId: "1", slug: "dine-in" }, { description: "Delivery Service", id: "14", isActive: true, name: "Delivery", serviceDetail: null, serviceId: "2", slug:"delivery" }, { description: "Collection Service", id: "15", isActive: true, name: "Collection", serviceDetail: null, serviceId: "3", slug: "collection" }],
isActive = Object.fromEntries(arr2.map(({ serviceId, isActive }) => [serviceId, isActive])),
result = arr1.map(o => ({ ...o, isActive: isActive[o.id] }));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Related
i want to loop through array of objects and check for a particular property and add a new property "disabled" to the array.
below is the array of objects
const arr_obj = [
{
id: "1",
name: "name1",
type: "type2",
children: [
{
id: "2",
name: "name2",
type: "type4",
children: [
{
id: "3",
name: "name3",
type: "type5",
},
},
{
id: "4",
name: "name4",
type: "type3",
children: [
{
id: "5",
name: "name5",
type: "type4",
children: [],
},
],
},
id: "6",
name: "name6",
type: "type3",
children: [
{
id: "7",
name: "name7",
type: "type4",
children: [],
},
],
}
},
.....//similar objects
];
so from above array of objects i want to check for each object if type === type2 and if type2 then add property disabled: false if not disabled: true.
below is what i have tried
const new_obj = React.useMemo(() => {
return arr_obj.map((arr) => ({
...arr,
disabled: arr?.type !== "type2" ? true : false,
}));
}, [arr_obj]);
this adds disabled property only to outer object it doesnt add to children object.
output with above snippet is like below,
const new_arr = [
{
id: "1",
name: "name1",
type: "type2",
disabled: false,
children: [
{
id: "2",
name: "name2",
type: "type4",
children: [
{
id: "3",
name: "name3",
type: "type5",
},
},
{
id: "4",
name: "name4",
type: "type3",
children: [
{
id: "5",
name: "name5",
type: "type4",
children: [],
},
],
},
id: "6",
name: "name6",
type: "type3",
children: [
{
id: "7",
name: "name7",
type: "type4",
children: [],
},
],
}
},
.....//similar objects
];
expected output is like below,
const new_arr = [
{
id: "1",
name: "name1",
type: "type2",
disabled: false,
children: [
{
id: "2",
name: "name2",
type: "type4",
disabled: true,
children: [
{
id: "3",
name: "name3",
type: "type5",
disabled: true,
},
},
{
id: "4",
name: "name4",
type: "type3",
disabled: true,
children: [
{
id: "5",
name: "name5",
type: "type4",
disabled: true,
children: [],
},
],
},
id: "6",
name: "name6",
type: "type3",
disabled: true
children: [
{
id: "7",
name: "name7",
type: "type4",
disabled: true,
children: [],
},
],
}
},
.....//similar objects
];
How can i fix the above snippet such that it adds disabled property to children too. could someone help me with this. thanks.
EDIT:
tried answer is like below,
function loop_children(children) {
if (!children || children.lengh <=0) {
return;
} else {
return children.map((child) => {
...child,
disabled: child?.type !== "type2" ? true : false,
children: loop_children(children)
})
};
}
}
return arr_obj.map((arr) => ({
...arr,
disabled: arr?.type !== "type2" ? true : false,
children: loop_children(arr.children) //seems like a problem here in adding children field again
}));
but this adds children array under children again.
This code doesnt work. it adds field disabled to children but also adds children within children.
could someone help me with this. thanks.
Not sure why all the others are mapping, just alter the object with a simple recursive call when it has a children property.
const arr_obj = [{
id: "1",
name: "name1",
type: "type2",
children: [{
id: "2",
name: "name2",
type: "type4",
children: [{
id: "3",
name: "name3",
type: "type5",
}, ]
}, ]
}];
const disableEnableObj = (arr, type) => {
arr.forEach(obj => {
obj.disabled = obj.type !== type;
obj.children && disableEnableObj(obj.children, type);
});
}
disableEnableObj(arr_obj, 'type2');
console.log(arr_obj);
You have to loop through the children too. It should look something like this:
function loop_children(children) {
return children.map((child) => {
...child,
disabled: child?.type !== "type2" ? true : false,
children: loop_children(children)
})
}
return arr_obj.map((arr) => ({
...arr,
disabled: arr?.type !== "type2" ? true : false,
children: loop_children(children)
}));
I have an array of objects which has further levels of children which follow the same pattern as that of their parents. A hierarchical tree view. My requirement is to do a recursion but in addition to that do updation to the parent array.
Input Array:
[
{
category_id: "1",
name: "Books",
parent_category: null,
children: [
{
category_id: "48",
name: "Arts, Film & Photography",
parent_category: "1",
children: [
{
category_id: "69",
name: "Architecture",
parent_category: "48",
children: [],
},
],
},
{
category_id: "20",
name: "Action & Adventure",
parent_category: "1",
children: [],
},
],
},
{
category_id: "2",
name: "Action & Adventure",
parent_category: null,
children: [],
},
]
I need to find and update all nodes that do not have further children with another key 'disabled: false' and those objects which has subsequent children with key 'disabled: true'.
expected result:
[
{
category_id: "1",
name: "Books",
parent_category: null,
disabled: true
children: [
{
category_id: "48",
name: "Arts, Film & Photography",
parent_category: "1",
disabled: true,
children: [
{
category_id: "69",
name: "Architecture",
parent_category: "48",
children: [],
disabled: false,
},
],
},
{
category_id: "20",
name: "Action & Adventure",
parent_category: "1",
children: [],
disabled: false,
},
],
},
{
category_id: "2",
name: "Action & Adventure",
parent_category: null,
children: [],
disabled: false,
},
]
Any help is appreciated and thanks in advance.
Below is the code that I tried, The problem is I cant align with the depth of the array with my updated array.
let newArray = []
const recur = (array) => {
array.map(childObj => {
/* console.log(childObj.category_id) */;
if(childObj.children.length) {
/* console.log('innerchild',childObj.category_id) */;
recur(childObj.children)
} else {
childObj['disabled'] = false
}
newArray.push(childObj);
})
}
recur(arr);
You could iterate the elements from the array and add a property, depending on the children length and iterate the children as well.
const
update = array => array.forEach(o => {
o.disabled = !!o.children.length;
update(o.children);
}),
data = [{ category_id: "1", name: "Books", parent_category: null, children: [{ category_id: "48", name: "Arts, Film & Photography", parent_category: "1", children: [{ category_id: "69", name: "Architecture", parent_category: "48", children: [] }] }, { category_id: "20", name: "Action & Adventure", parent_category: "1", children: [] }] }, { category_id: "2", name: "Action & Adventure", parent_category: null, children: [] }];
update(data);
console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }
If you do not like to mutate the data, you could map new objects.
const
update = ({ children, ...o }) => ({
...o,
disabled: !!children.length,
children: children.map(update)
}),
data = [{ category_id: "1", name: "Books", parent_category: null, children: [{ category_id: "48", name: "Arts, Film & Photography", parent_category: "1", children: [{ category_id: "69", name: "Architecture", parent_category: "48", children: [] }] }, { category_id: "20", name: "Action & Adventure", parent_category: "1", children: [] }] }, { category_id: "2", name: "Action & Adventure", parent_category: null, children: [] }];
console.log(data.map(update));
.as-console-wrapper { max-height: 100% !important; top: 0; }
I have to form an array of object in another array of object based on id. I was able to group the object based the "applicationId" but was not able to group the inside array of attributes and values array. Also the above code gives me duplicate objects. Please help with this I know its a small fix but I spend whole day still no result.stackblitz. Expected output commented below in stackblitz
data.map((el) => {
el.attribute.map((elm) => {
elm.options.map(em => {
permissions.push({
applicationId: el.application, attributes: [{ name: elm.name, value: em.value, disabled: true
}]
})
})
})
});
Input Object
[
{
application: "abc",
attribute: [
{
description: "abc description1"
name: "audio"
options:[
{name: "Yes", value: "Y"}
{name: "No", value: "N"}
]
},
{
description: "abc description2"
name: "video"
options:[
{name: "true", value: "T"}
{name: "false", value: "F"}
]
}
{
description: "abc description3"
name: "call"
options:[
{name: "Yes", value: "Y"}
{name: "false", value: "F"}
]
}
]
},
{
application: "def",
attribute: [
{
description: "def description1"
name: "audio"
options:[
{name: "Yes", value: "Y"}
{name: "No", value: "N"}
]
},
{
description: "def description2"
name: "video"
options:[
{name: "true", value: "T"}
{name: "false", value: "F"}
]
}
{
description: "def description3"
name: "call"
options:[
{name: "Yes", value: "Y"}
{name: "false", value: "F"}
]
}
]
}
]
Expected Output:
permissions:[
{
applicationId:abc
attributes:
[
{
name:audio
value:["Y","N"]
disabled: true
},
{
name:video,
value:["T","F"]
disabled: true
},
{
name:call,
value:["Y","F"]
disabled: true
}
]
},
{
applicationId: def
attributes:
[
{
name:audio
value:["Y","N"]
disabled: true
},
{
name:video,
value:["T","F"]
disabled: true
},
{
name:call,
value:["Y","F"]
disabled: true
}
]
}
]
You could do so using few array maps.
Try the following
var input = [ { application: "abc", attribute: [ { description: "abc description1", name: "audio", options: [ { name: "Yes", value: "Y" }, { name: "No", value: "N" } ] }, { description: "abc description2", name: "video", options: [ { name: "true", value: "T" }, { name: "false", value: "F" } ] }, { description: "abc description3", name: "call", options: [ { name: "Yes", value: "Y" }, { name: "false", value: "F" } ] } ] }, { application: "def", attribute: [ { description: "def description1", name: "audio", options: [ { name: "Yes", value: "Y" }, { name: "No", value: "N" } ] }, { description: "def description2", name: "video", options: [ { name: "true", value: "T" }, { name: "false", value: "F" } ] }, { description: "def description3", name: "call", options: [ { name: "Yes", value: "Y" }, { name: "false", value: "F" } ] } ] } ];
var output = input.map(item => ({
applicationId: item.application,
attributes: item.attribute.map(attr => ({
name: attr.name,
value: attr.options.map(option => option.value),
disabled: true
}))
}));
console.log(output);
I've modified your Stackblitz.
Sidenote: Please try to post a valid object in the question. It'll make it much easier and quicker to reproduce the issue. Much of my time was spent not in the solution but in fixing the object.
How to change property in the object array based on array of values in javascript,
I have object obj and parameter as list, should changed the property checked to true, if title matched with the list in javascript
if the title is matched with list and has children, then checked: true
ie.countries title is matched with list , then children also change the property checked: true
if the children title is matched , then change checked: true for that object only
ie.clothes title is matched with list , then change the property checked: true for that object only
I stuck to do with list of arrays as param,
var obj = [{
title: "Sample",
checked: false,
children: [{
title: "products",
checked: false,
children: [{
title: "clothes",
id: 1,
checked: false
},
{
title: "electronics",
id: 2,
checked: false
}
]
},
{
title: "countries",
checked: false,
children: [{
title: "IN",
id: 1,
checked: false
},
{
title: "TH",
id: 2,
checked: false
}
]
}
]
}];
var list = ["clothes", "countries"];
Expected Output:
[{
title: "Sample",
checked: false,
children: [
{
title: "products",
checked: false,
children: [
{title: "clothes", id: 1, checked: true},
{title: "electronics", id: 2, checked: false}
]
},{
title: "countries",
checked: true,
children: [
{title: "IN", id: 1, checked: true},
{title: "TH", id: 2, checked: true}
]
}
]
}]
You need some recursion, to handle any depth of nesting:
With this solution, it is very generic, you can change the childrenProp, matchProp, checkedProp etc. and it will allow you to search as deep as you need to in a nested structure.
const obj = [
{
title: "Sample",
checked: false,
children: [
{
title: "products",
checked: false,
children: [
{title: "clothes", id: 1, checked: false},
{title: "electronics", id: 2, checked: false}
]
},
{
title: "countries",
checked: false,
children: [
{title: "IN", id: 1, checked: false},
{title: "TH", id: 2, checked: false}
]
}
]
}
];
var list=["clothes", "countries"];
checkPropertyForMatch(obj, list);
console.log(obj);
checkPropertyForMatch(obj, ['electronics']);
console.log(obj);
function checkPropertyForMatch(inputArr, matchList, matchProp, childrenProp, checkedProp){
//default params, or they can be overwritten:
matchProp = matchProp || 'title';
childrenProp = childrenProp || 'children';
checkedProp = checkedProp || 'checked';
innerRecursive(inputArr, matchList);
//recursively search the nested object:
function innerRecursive(currArr, list){
for (item of currArr){
if ( list.includes(item[matchProp]) ){
item[checkedProp] = true;
if (item[childrenProp]){
//this parent matched, so mark all children as marked too:
markAllChildrenChecked(item[childrenProp]);
}
}
else {
item[checkedProp] = false;
if (item[childrenProp]) {
//it didn't match but it has children, so search them too:
innerRecursive(item[childrenProp], list)
}
}
}
}
//this recursively marks all children as checked = true:
function markAllChildrenChecked(currArr){
for (item of currArr){
item[checkedProp] = true;
if (item[childrenProp]){
markAllChildrenChecked(item[childrenProp]);
}
}
}
}
.as-console-wrapper { max-height: 100% !important; top: 0; }
Output:
[
{
"title": "Sample",
"checked": false,
"children": [
{
"title": "products",
"checked": false,
"children": [
{"title": "clothes", "id": 1, "checked": true},
{"title": "electronics", "id": 2, "checked": false}
]
},
{
"title": "countries",
"checked": true,
"children": [
{"title": "IN", "id": 1, "checked": true},
{"title": "TH", "id": 2, "checked": true}
]
}
]
}
]
The trick here is below:
if (list.indexOf(ele.title) > -1 || list.indexOf(el.title) > -1) {
el.checked = true;
}
var obj = [{
title: "Sample",
checked: false,
children: [{
title: "products",
checked: false,
children: [{
title: "clothes",
id: 1,
checked: false
},
{
title: "electronics",
id: 2,
checked: false
}
]
},
{
title: "countries",
checked: false,
children: [{
title: "IN",
id: 1,
checked: false
},
{
title: "TH",
id: 2,
checked: false
}
]
}
]
}];
var list = ["clothes", "countries"];
obj.forEach(elem => {
elem.children.forEach(ele => {
ele.children.forEach(el => {
if (list.indexOf(ele.title) > -1 || list.indexOf(el.title) > -1) {
el.checked = true;
}
})
})
})
console.log(obj)
I am using treegrid of jqgrid, in which i want multiselect which is not possible , so i explicitely put a checkbox column. Now I want to know how to iterate each row of tree grid and access particular cell of that row, so that I can do specific action on it. Thank in advance.
The simplest way to implement your requirements seems me to include additional column in the tree grid which has the checkbox:
You have not posted the code of the grid which you are using. It is even not clear if you are using local tree grid or a remote one. In the following example I am showing how to implement the checkbox from the "Enabled" column in case of local grid. So you can have the following results:
The corresponding demo you will find here.
The HTML code is:
<fieldset style="float:left">
<input id="getSelected" type="button" value="Get Selected"/>
</fieldset>
<fieldset style="clear:both; float:left">
<legend>Seleceted Ids</legend>
<p id="ids"></p>
</fieldset>
<fieldset style="clear:both; float:left">
<legend>Selected Names</legend>
<p id="names"></p>
</fieldset>
<div style="clear:left">
<table id="treegrid"><tr><td/></tr></table>
</div>
and the JavaScript code:
$(function () {
'use strict';
var mydata = [
{ id: "1", name: "Cash", num: "100", debit: "400.00", credit: "250.00", balance: "150.00", enbl: "1",
level: "0", parent: "null", isLeaf: false, expanded: false },
{ id: "2", name: "Cash 1", num: "1", debit: "300.00", credit: "200.00", balance: "100.00", enbl: "0",
level: "1", parent: "1", isLeaf: false, expanded: false, loaded: true },
{ id: "3", name: "Sub Cash 1", num: "1", debit: "300.00", credit: "200.00", balance: "100.00", enbl: "1",
level: "2", parent: "2", isLeaf: true, expanded: false },
{ id: "4", name: "Cash 2", num: "2", debit: "100.00", credit: "50.00", balance: "50.00", enbl: "0",
level: "1", parent: "1", isLeaf: true, expanded: false },
{ id: "5", name: "Bank\'s", num: "200", debit: "1500.00", redit: "1000.00", balance: "500.00", enbl: "1",
level: "0", parent: "null", isLeaf: false, expanded: true, loaded: true },
{ id: "6", name: "Bank 1", num: "1", debit: "500.00", credit: "0.00", balance: "500.00", enbl: "0",
level: "1", parent: "5", isLeaf: true, expanded: false },
{ id: "7", name: "Bank 2", num: "2", debit: "1000.00", credit: "1000.00", balance: "0.00", enbl: "1",
level: "1", parent: "5", isLeaf: true, expanded: false },
{ id: "8", name: "Fixed asset", num: "300", debit: "0.00", credit: "1000.00", balance: "-1000.00", enbl: "0",
level: "0", parent: "null", isLeaf: true, expanded: false }],
grid = $("#treegrid"),
getColumnIndexByName = function (columnName) {
var cm = grid.jqGrid('getGridParam', 'colModel'), i, l = cm.length;
for (i = 0; i < l; i++) {
if (cm[i].name === columnName) {
return i; // return the index
}
}
return -1;
},
iCol;
grid.jqGrid({
datatype: "local",
colNames: ["id", "Account", "Acc Num", "Debit", "Credit", "Balance", "Enabled"],
colModel: [
{name: 'id', index: 'id', width: 1, hidden: true, key: true},
{name: 'name', index: 'name', width: 180},
{name: 'num', index: 'acc_num', width: 80, align: "center"},
{name: 'debit', index: 'debit', width: 80, align: "right"},
{name: 'credit', index: 'credit', width: 80, align: "right"},
{name: 'balance', index: 'balance', width: 80, align: "right"},
{name: 'enbl', index: 'enbl', width: 60, align: 'center',
formatter: 'checkbox', editoptions: {value: '1:0'},
formatoptions: {disabled: false}}
],
height: '100%',
rowNum: 10000,
sortname: 'id',
treeGrid: true,
loadonce: true,
treeGridModel: 'adjacency',
treedatatype: 'local',
ExpandColumn: 'name',
caption: 'Demonstrate how to use Tree Grid for the Adjacency Set Model'
});
// we have to use addJSONData to load the data
grid[0].addJSONData({
total: 1,
page: 1,
records: mydata.length,
rows: mydata
});
iCol = getColumnIndexByName('enbl');
// nth-child need 1-based index so we use (iCol+1) below
$("tbody>tr.jqgrow>td:nth-child(" + (iCol + 1) + ")>input", grid[0]).change(function (e) {
var isChecked = $(this).attr("checked"), rowid, dataIndex,
tr = $(e.target, grid[0].rows).closest("tr.jqgrow");
if (tr.length > 0) {
rowid = tr[0].id;
dataIndex = grid[0].p._index[rowid];
if (typeof dataIndex !== "undefined" && dataIndex >= 0) {
grid[0].p.data[dataIndex].enbl = isChecked ? "1" : "0";
}
}
e.preventDefault();
});
$("#getSelected").click(function () {
var ids = [], names = [], i, data = grid[0].p.data, l = data.length, dataItem;
for (i = 0; i < l; i++) {
dataItem = data[i];
if (dataItem.enbl === "1") {
ids.push(dataItem.id);
names.push(dataItem.name);
}
}
$("#ids").html(ids.join(", "));
$("#names").html(names.join(", "));
});
});
I think there not so difficult.
$("#YourTreegridContainerTag").find(":input[type=='checkbox']").each(function()
{
$(this).attr("cheked", "checked");
});
and for disablling:
$("#YourTreegridContainerTag").find(":input[type=='checkbox']").each(function()
{
$(this).removeAttr("cheked");
});