Hi I am developing a Table components where I need to populate the data in table body dynamically. I am maintaining the bodyData in arrayOf:[{}]. Cells will be created dynamically based on the values in the mock data. I need to pass four different data in body from mockdata. Now all are getting passed as children. Now I need to display one of the data in table cell in badge format. For this I am trying to pass multiple children so that I can render one of the children in badge format. But When I am passing more than one children component is rendering last children value only. Could any one help me how to pass (Brand value in the table in form of badge). Thanks in advance. I have wrote down the working code and mockdata.
import mockData from './mock-data/';
const createCell = cell => ({ key: cell.key, children: cell.children});
//tried to pass like cell => ({ key: cell.key, children: cell.customerName,
//children:cell.customerAddr})
const createCellsForRow = cells => cells.map(cell => createCell(cell));
const StTable = () => {
const [selectedKey, setSelectedKey] = useState([]);
const handleRowToggle = (event, metaData) => {
event.preventDefault();
if (selectedKey !== metaData.key) {
setSelectedKey(metaData.key);
}
};
const createRow = rowData => (
{
key: rowData.key,
cells: createCellsForRow(rowData.cells),
toggleAction: {
metaData: { key: rowData.key },
onToggle: handleRowToggle,
isToggled: selectedKey === rowData.key,
toggleLabel: rowData.toggleText,
},
}
);
const createRows = data => data.map(childItem => createRow(childItem));
return (
<Table
summaryId="example-single-select"
summary="This table shows an implementation of single row selection."
numberOfColumns={4}
cellPaddingStyle="standard"
rowStyle="toggle"
dividerStyle="horizontal"
headerData={{
selectAllColumn: {
checkLabel: 'Single Selection',
},
cells: [
{ key: 'cell-0', id: 'toggle-0', children: 'Name' },
{ key: 'cell-1', id: 'toggle-1', children: 'Address' },
{ key: 'cell-2', id: 'toggle-2', children: 'Phone Number' },
{ key: 'cell-3', id: 'toggle-3', children: 'Brand' },//I need to pass this is as
//badge format.
],
}}
bodyData={[
{
rows: createRows(mockData),
},
]}
/>
);
};
export default StTable;
//mockData Sample
[
{
"key":"row-0",
toggleText:"txt",
"cells":[
{ key: 'cell-0', id: 'toggle-0', children: 'ABC' },
{ key: 'cell-1', id: 'toggle-1', children: 'ABC123' },
{ key: 'cell-2', id: 'toggle-2', children: 'P1234567890' },
{ key: 'cell-3', id: 'toggle-3', children: ['A', 'B'] },
]
]
//I am trying to change the structure because (I need to display the brand in badge format)
[
{
"key":"row-0",
toggleText:"txt",
"cells":[
{ key: 'cell-0', id: 'toggle-0', customerName: 'ABC' },
{ key: 'cell-1', id: 'toggle-1', customerAddr: 'ABC123' },
{ key: 'cell-2', id: 'toggle-2', customerPhNo: 'P1234567890' },
{ key: 'cell-3', id: 'toggle-3', customerBrand: ['A', 'B'] },
]
]
//Table Component
const createCell = cell => ({ key: cell.key, children: cell.title });
const createCellsForRow = cells => cells.map(cell => createCell(cell));
const Table = () => {
const [selectedKey, setSelectedKey] = useState([]);
const handleRowToggle = (event, metaData) => {
event.preventDefault();
if (selectedKey !== metaData.key) {
setSelectedKey(metaData.key);
}
};
const createRow = rowData => (
{
key: rowData.key,
cells: createCellsForRow(rowData.cells),
toggleAction: {
metaData: { key: rowData.key },
onToggle: handleRowToggle,
isToggled: selectedKey === rowData.key,
toggleLabel: rowData.toggleText,
},
}
);
const createRows = data => data.map(childItem => createRow(childItem));
return (
<Table
numberOfColumns={4}
cellPaddingStyle="standard"
rowStyle="toggle"
dividerStyle="horizontal"
headerData={{
selectAllColumn: {
checkLabel: 'Single Selection',
},
cells: [
{ key: 'cell-0', id: 'toggle-0', children: 'Name' },
{ key: 'cell-1', id: 'toggle-1', children: 'Address' },
{ key: 'cell-2', id: 'toggle-2', children: 'Phone Number' },
{ key: 'cell-3', id: 'toggle-3', children: 'Email Id' },
],
}}
bodyData={[
{
rows: createRows(mockData),
},
]}
/>
);
};
export default Table;
Related
I want to search in a big array for different id from another array and print all intersections of those two arrays
I want to map through my bigTable and I want to create another array of correspondence, each found element must contain all fields+tableName+tableID like this :
const output = [{
ID: 1234,
title: 'title1',
TableName: 'loramIpsum',
TableId: 11,
},
{
ID: 98523,
title: 'mylasttitle',
TableName: 'table2',
TableId: 87545,
},
{
ID: 97766,
title: 'mylastdata',
TableName: 'table2',
TableId: 87545,
},
]
I've create a function but I think there is another best and sample solution, this is my function :
const getResult = (wantedData, bigArray) => {
return wantedData.flatMap((id) =>
bigArray.flatMap((family) =>
family.Tables.flatMap((table) => {
let item = table.myDatas.find((el) => el.ID === id);
if (item) {
item.Table = table.TableName;
item.familyId = family.GridId;
return item;
}
}).filter((result) => result !== undefined)
)
);
};
console.log(getResult(wantedData, bigArray))
<script>
const wantedData = [1235, 98523, 97766];
const bigArray = [{
bigArrayId: 1111,
Tables: [{
TableId: 11,
TableName: 'loramIpsum',
myDatas: [{
ID: 1234,
title: 'title1',
},
{
ID: 1235,
title: 'title2',
},
],
}, ],
},
{
bigArrayId: 674665,
Tables: [{
TableId: 87545,
TableName: 'table2',
myDatas: [{
ID: 98523,
title: 'mylasttitle',
},
{
ID: 24134,
title: 'alex',
},
{
ID: 97766,
title: 'mylastdata',
},
],
}, ],
},
];
</script>
Any help please ? Can I do it with recursive function ?
I think you need to solve this problem in two steps:
First, create a flat array of tables
Then filter the array by conditions
const bigArray=[{bigArrayId:1111,Tables:[{TableId:11,TableName:"loramIpsum",myDatas:[{ID:1234,title:"title1"},{ID:1235,title:"title2"}]}]},{bigArrayId:674665,Tables:[{TableId:87545,TableName:"table2",myDatas:[{ID:98523,title:"mylasttitle"},{ID:24134,title:"alex"},{ID:97766,title:"mylastdata"}]}]}];
const wantedData = [1235, 98523, 97766];
const flatTables = bigArray.flatMap(({ Tables }) =>
Tables.flatMap(({ myDatas, TableId, TableName }) =>
myDatas.map((data) => ({ ...data, TableId, TableName })) ));
const result = flatTables.filter(({ ID }) => wantedData.includes(ID));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I think if you do it something like this you'll be able to map after you've found the right things rather than mapping everything and then filtering that result:
const bigArray = [{ bigArrayId: 1111, Tables: [{ TableId: 11, TableName: 'loramIpsum', myDatas: [{ ID: 1234, title: 'title1', }, { ID: 1235, title: 'title2', }, ], }, ], }, { bigArrayId: 674665, Tables: [{ TableId: 87545, TableName: 'table2', myDatas: [{ ID: 98523, title: 'mylasttitle', }, { ID: 24134, title: 'alex', }, { ID: 97766, title: 'mylastdata', }, ], }, ], }, ];
const wantedData = [1235, 98523, 97766];
const wanted_set = new Set(wantedData);
const push_concat = (arr1, arr2) => {
for(let i = 0; i < arr2.length; i++)
arr1.push(arr2[i]);
return arr1;
};
const res = bigArray.reduce(
(acc, { Tables }) =>
push_concat(acc,
Tables.flatMap(({ TableId, TableName, myDatas }) =>
myDatas
.filter(({ ID }) => wanted_set.has(ID))
.map(({ ID, title }) => ({ ID, title, TableId, TableName }))
)
),
[]
);
console.log(res);
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.
I have this code structure:
const data = [
{
name: 'Lebron',
sports: 'Basketball',
},
{
name: 'Durant',
sports: 'Basketball',
},
{
name: 'Federrer',
sports: 'Tennis',
},
{
name: 'Nadal',
sports: 'Tennis',
},
];
and I'm trying to transform it into this:
const treeData = [
{
title: 'Select All',
key: 'All',
children: [
{
title: 'Basketball',
key: 'Basketball',
children: [
{
title: 'Lebron',
key: 'Lebron',
},
{
title: 'Durant',
key: 'Durant',
},
],
},
{
title: 'Tennis',
key: 'Tennis',
children: [
{
title: 'Federrer',
key: 'Federrer',
},
{
title: 'Nadal',
key: 'Nadal',
},
],
},
],
},
];
to use in Ant Design Tree link.
Right now my plan is to get all the sports like this:
let sports = data.map(({ sports }) => sports);
sports = [...new Set(sports)];
but after that I have no idea on what should be my next step to achieve the treeData
You can use .reduce() to accumulate all sports to a Map, where each sport is a key and each value for the sport is an array of associated names. Once you have built the Map, you can use Array.from() to convert your map into your desired children array. This can be done by providing a mapping function as the second argument to Array.from(), and using it to convert each entry ([key, value]) pair to an object of your desired structure.
See example below:
const data = [ { name: 'Lebron', sports: 'Basketball', }, { name: 'Durant', sports: 'Basketball', }, { name: 'Federrer', sports: 'Tennis', }, { name: 'Nadal', sports: 'Tennis', }, ];
const children = Array.from(data.reduce((m, {name, sports}) =>
m.set(sports, [...(m.get(sports) || []), name])
, new Map), ([key, arr]) => ({title: key, key, children: arr.map(title => ({title, key: title}))}));
const treeData = [{title: 'Select All', key: 'All', children}];
console.log(treeData);
const data = [
{
name: 'Lebron',
sports: 'Basketball',
},
{
name: 'Durant',
sports: 'Basketball',
},
{
name: 'Federrer',
sports: 'Tennis',
},
{
name: 'Nadal',
sports: 'Tennis',
},
];
const dataMap: Record<string, string[]> = {};
data.forEach(({ name, sports }) => {
dataMap[sports] ??= []
dataMap[sports].push(name)
})
const treeData = [{
title: 'Select All',
key: 'All',
children: Object.entries(dataMap).map(([sport, names]) => ({
title: sport,
key: sport,
children: names.map(name => ({
title: name,
key: name
}))
}))
}]
Here's a two-steps way of get the children of your final object:
First, use a reduce to create an object of sports/children, where children matches what you have in your final output:
const middle = data.reduce((transformed, item) => {
if (!transformed[item.sports]) {
transformed[item.sports] = [];
}
transformed[item.sports].push({
title: item.name,
key: item.name
});
return transformed;
}, {});
Then map the results of the reduce function to reshape the object:
const results = Object.entries(middle).map(([key, children]) => ({
title: key,
key,
children
}));
I'm trying to get the structure below.
https://imgur.com/NBRGlhM
Three columns, with titles, and column cards that can be moved within only one column. this.state.item ['lists'] moving to the component SortableList. Then iterates after items.map ((item, index) => and moves to the component SortableItem. Then iterates aftervalue.listItems and wants to display the title of columns and cards in the column. I get the error:
Cannot read property ' indexOf 'of undefined
Demo here: https://stackblitz.com/edit/react-jpszoq
import {SortableContainer, SortableElement} from 'react-sortable-hoc';
import arrayMove from 'array-move';
const SortableItem = SortableElement(({value}) => {
return(
value.listItems.map((it, index) => {
<li>{it.title}</li>
})
)
})
const SortableList = SortableContainer(({items}) => {
console.log(items)
return (
<ul>
{
items.map((item, index) =>
<div>{item.name}
<SortableItem key={`item-${item.id}`} index={index} value={item} />
</div>
)
}
</ul>
);
});
class App extends Component {
constructor() {
super();
this.state = {
item: {
id: "abc123",
name: "AAA",
lists: [
{
id: "def456",
list_id: "654wer",
title: 'List1',
desc: "description",
listItems: [
{
id: "ghj678",
title: "ListItems1",
listItemsId: "88abf1"
},
{
id: "poi098",
title: "ListItems2",
listItemsId: "2a49f25"
}
]
},
{
id: "1ef456",
list_id: "654wer",
title: 'List 2',
desc: "description",
listItems: [
{
id: "1hj678",
title: "ListItems3",
listItemsId: "18abf1"
},
{
id: "1oi098",
title: "ListItems4",
listItemsId: "1a49f25"
}
]
},
{
id: "2ef456",
title: 'List 3',
list_id: "254wer",
desc: "description",
listItems: [
{
id: "2hj678",
title: "ListItems5",
listItemsId: "28abf1"
},
{
id: "2oi098",
title: "ListItems6",
listItemsId: "234a49f25"
}
]
}
]
}
};
}
onSortEnd = ({oldIndex, newIndex}) => {
this.setState(({lists}) => ({
lists: arrayMove(lists, oldIndex, newIndex),
}));
};
render() {
return <SortableList items={this.state.item['lists']} onSortEnd={this.onSortEnd} />;
}
}
you're missing a return on L14 in the function passed to listItems.map. Alternatively, you could remove the braces.
I'm a learner developer, and I'm build a app with a tree menu(react + redux + sagas), but I'm getting some errors of Mutation State, I saw what best practices is stay de state flat as possible, but I didn't finded one menu tree what work with a flat state, so my data is look this:
menuTree: [{
id: 'id-root',
name: 'root',
toggled: true,
children: [
{
id: 'id-parent1',
name: 'parent1',
toggled: true,
children: [
{
id: '123',
name: 'parent1_child1'
},
{
id: '234',
name: 'parent1_child2'
}
]
},
{
id: 'id-loading-parent',
name: 'loading parent',
loading: true,
children: []
},
{
id: 'id-parent2',
name: 'parent2',
toggled: true,
children: [
{
id: 'parent2_children1',
name: 'nested parent2',
children: [
{
id: '345',
name: 'parent2 child 1 nested child 1'
},
{
id: '456',
name: 'parent2 child 1 nested child 2'
}
]
}
]
}
]
}],
And my redux action:
case types.SOLUTION__MENUCURSOR__SET:
// console.log('action payload', action.payload);
// console.log('state', state);
const cursor = action.payload.cursor;
// console.log('set menu cursor action', cursor);
return {
...state,
menuTree: state.menuTree.map(
function buscaIdMenuTree(currentValue, index, arr){
if(currentValue.id){
if(currentValue.id.includes(cursor.id)){
currentValue.toggled = action.payload.toggled;
return arr;
}else{
if(currentValue.children)
{
currentValue.children.forEach(function(currentValue, index, arr){
return buscaIdMenuTree(currentValue, index, arr);
});
}
}
return arr;
}
}
)[0]
};
The code works but I get Mutation State Error, so someone can help me to fix it ?
You can rebuild your menu as a plain list:
let menuTree = [{
id: 'id-root',
name: 'root',
toggled: true,
parent: null
},{
id: 'id-parent1',
name: 'parent1',
toggled: true,
parent: 'id-root'
},{
id: '123',
name: 'parent1_child1',
parent: 'id-parent1'
},{
id: '234',
name: 'parent1_child1',
parent: 'id-parent1'
},
{
id: 'id-loading-parent',
name: 'loading parent',
loading: true,
parent: 'id-root'
},{
id: 'id-parent2',
name: 'parent2',
toggled: true,
parent: 'id-root'
},{
id: 'parent2_children1',
name: 'nested parent2',
parent: 'id-parent2'
},{
id: '345',
name: 'parent2 child 1 nested child 1',
parent: 'parent2_children1'
},
{
id: '456',
name: 'parent2 child 1 nested child 2',
parent: 'parent2_children1'
}]
then if your menu renderer require a tree you can convert the list to a tree so inside the component renderer this.menuTree will be a tree:
const buildTree = (tree, cParent = null) => {
return tree.filter(cNode => cNode.parent == cParent).reduce((curr, next) => {
let cNode = {...next, children: buildTree(tree, next.id)}
delete cNode.parent
return [...curr, cNode]
}, [])
}
function mapStateToProps(state) {
return {
mapTree: builTree(state.mapTree)
};
}
export default connect(mapStateToProps)(YourComponent);
Inside the mutation now you just need to create a list of node that needs to be toggled and then map the state accordingly
case types.SOLUTION__MENUCURSOR__SET:
// console.log('action payload', action.payload);
// console.log('state', state);
const cursor = action.payload.cursor;
// console.log('set menu cursor action', cursor);
const getToggleList = (tree, cursor) => {
let target = tree.find(cNode => cNode.id == cursor.id)
if(target.parent != null){
let parent = tree.find(cNode => cNode.id == target.parent)
return [target.parent, ...getToggleList(tree, parent)]
}else{
return []
}
}
let toggleList = [cursor.id, ...getToggleList(state.menuTree, cursor.id)]
return {
...state,
menuTree: state.menuTree.map(node => ({...node, toggle: toggleList.includes(node.id)}))
};