Iterate over JS object of arrays - javascript

I have this object that I'm trying to loop over in a form but really can't get it to work. Here is sample of the object.
const data = {
"Social Security": [
{
label: "Deduction Type",
value: "Social Security",
name: "SocialSecurity"
},
{
label: "Employer Rate",
value: "12.4%",
name: "SocialEmployer"
},
{
label: "Employee Rate",
value: "6.2%",
name: "SocialEmployee"
}
],
"Medicare": [
{
label: "Deduction Type",
value: "Medicare",
name: "Medicare"
},
{
label: "Employer Rate",
value: "1.45%",
name: "MedicareEmployer"
},
{
label: "Employee Rate",
value: "2.9%",
name: "MedicareEmployee"
}
]
}
form implementation
<Formik>
{({ values, isSubmitting, resetForm, setFieldValue }) => (
<Form id="payrollSettingsForm" >
<Grid container className={classes.border}>
<Grid item xs={12} md={4}>
{Object.entries(data).map(arr =>{
Array.isArray(arr) && arr.map(elm =>{
return (<TextField
label={elm.label}
value={elm.value}
name={elm.name}
/>)
})
})}
</Grid>
</Grid>
...rest of the form
</Form>
</Formik>
Tried many approaches like Object.fromEntries(). forEach I think all the methods I can find example and keep failing, maybe I'm doing something wrong, any help will be appreciated.

{Object.entries(data).map(([key, val]) =>{
return val.map(elm =>{
return (
<TextField
label={elm.label}
value={elm.value}
name={elm.name}
/>
)
})
})}

Map should return an element on each iteration. In case you don't want to display return null else return a react node.
<Grid item xs={12} md={4}>
{Object.entries(data).map(arr => {
Array.isArray(arr) ? arr.map(elm => {
return (<TextField
label={elm.label}
value={elm.value}
name={elm.name}
/>)
}) : null
})}
</Grid>

Related

React Native - How to send objects in renderItem?

I'm receiving data from api like this:
{
"isTrue": true,
"data1": {
"username": "user1",
"images": [
"image1.jpg",
"image2.jpg"
]
},
"data2": {
"location": "new york",
"age": "80"
}
}
and setting it in my state as details.
I want to display data in flatlist, so I do this:
<FlatList
data={state.details}
renderItem={({item}) => {
<Details item={item} />;
}}
></FlatList>
in my component I render data like:
export default Details = ({item}) => {
return item
? Object.values(item).map(value => {
<Text>{value.data1?.username}</Text>;
})
: null;
};
Why don't the items render?
Make sure u pass Array to flat list
like :
const DATA = [
{
id: "bd7acbea-c1b1-46c2-aed5-3ad53abb28ba",
title: "First Item",
},
{
id: "3ac68afc-c605-48d3-a4f8-fbd91aa97f63",
title: "Second Item",
},
{
id: "58694a0f-3da1-471f-bd96-145571e29d72",
title: "Third Item",
},
];
flat list will do for loop for you, so u don't need to values(item).map you can do:
export default Details = ({item}) => {
return
<View>
<Text>{item.isTrue}</Text>
<Text>{item.data1.username}</Text>
</View>
};
change
renderItem={({item}) => {
<Details item={item} />;
}}
to
renderItem={({item}) => {
return <Details item={item} />;
}}
or
renderItem={({item}) => (<Details item={item} />)}
finally don't forget to add <View></View> as parent for <Text><Text>

How to filter option in FormSelect in react?

I do not have experience in FrontEnd development so I try to research how to filter the options in select. However, I can not find a way to do it.
I want to filter up options based on the selection from the first input. So if Protocol === 'A', then option should only show By Workstation
From the internet, they only showed where we declare the options in a function and create a filter function, then call the filterfunction to return the value.
What I want is directly filter the options or maybe create some logic to filter them. Please give some advice on this.
<Grid container spacing={2}>
<Grid item xs={12}>
<FormSelect
field={'type'}
label={'Protocol'}
margin={'none'}
form={formik}
options={Object.values(ReceiverType).map((value) => ({
label: value,
value: value,
}))}
/>
</Grid>
<Grid item xs={12} sm={12}>
<FormSelect
field={'settlementMode'}
label={'Settlement Mode'}
form={formik}
options={[
{ label: 'By Workstation', value: SettlementMode.BY_WORKSTATION },
{ label: 'By MID', value: SettlementMode.BY_MID },
{ label: 'All Terminals', value: SettlementMode.ALL },
]}
/>
</Grid>
Eg:
<Grid item xs={12} sm={12}>
<FormSelect
field={'settlementMode'}
label={'Settlement Mode'}
form={formik}
if (Protocol === A) {
options={[
{ label: 'By Workstation', value: SettlementMode.BY_WORKSTATION },
]}
} else {
options={[
{ label: 'By Workstation', value: SettlementMode.BY_WORKSTATION },
{ label: 'By MID', value: SettlementMode.BY_MID },
{ label: 'All Terminals', value: SettlementMode.ALL },
]}
}
/>
</Grid>

How can I create a menu with my json info with REACT

what I try to do is to have the same display as this picture :
So in my menu the plant type (Type of plant1) is displayed above a gray bar and when you click on the down chevron then you can see all the plants name, related to this type, with checkboxes on left, by default there will be all checked. And the blue rectangle indicates the number of plants that have been selected.
How can I do that, which package can help me in REACT?
Here my plants.json :
{
"plants_type": [
{
"_id_type": "1",
"name_type": "Type of plant1",
"plants": [
{
"name": "Plant1.1",
"_id": "2"
},
{
"name": "Plant1.2",
"_id": "3"
}
]
},
{
"_id_type": "4",
"name_type": "Type of plant2",
"plants": [
{
"name": "Plant2.1",
"_id": "5"
},
{
"name": "Plant2.2",
"_id": "6"
}
]
}
]
}
You can create a dropdown list on your own like below. I have added the logic of selecting items to the data itself.
You can keep a component called Category to keep a single state of the parent menu item. Whether it's open or not. Then iterate over the plants as checkbox inputs to make them selectable.
I have used a simple initialize function to make all the items selected initially. This should work as you expect. Add a console log of selectionMenu to see how selected property changes while toggling items.
Move the inline styles to CSS classes to make the code more clear.
const data = { plants_type: [ { _id_type: "1", name_type: "Type of plant1", plants: [ { name: "Plant1.1", _id: "2" }, { name: "Plant1.2", _id: "3" } ] }, { _id_type: "4", name_type: "Type of plant2", plants: [ { name: "Plant2.1", _id: "5" }, { name: "Plant2.2", _id: "6" } ] } ] };
const Category = ({ _id_type, name_type, plants, changeSelection }) => {
const [toggleState, setToggleState] = React.useState(false);
return (
<div key={_id_type}>
<div
style={{
cursor: "pointer",
userSelect: "none",
display: "flex",
margin: "2px",
backgroundColor: "lightgray"
}}
onClick={() => setToggleState((prev) => !prev)}
>
<div>{name_type}</div>
<div
style={{
backgroundColor: "blue",
color: "white",
padding: "0px 10px",
marginLeft: "auto"
}}
>
{plants.filter(({ selected }) => selected).length}
</div>
</div>
<div style={{ marginLeft: "10px" }}>
{toggleState &&
plants.map(({ name, _id, selected }) => (
<div key={_id}>
<input
key={_id}
type="checkbox"
value={name}
checked={selected}
onChange={(e) => changeSelection(_id_type, _id, e.target.value)}
/>
{name}
</div>
))}
</div>
</div>
);
};
const App = () => {
const initializeSelectionMenu = (data) => {
return data.map((item) => {
return {
...item,
plants: item.plants.map((plant) => ({ ...plant, selected: true }))
};
});
};
const [selectionMenu, setSelectionMenu] = React.useState(
initializeSelectionMenu(data.plants_type)
);
console.log(selectionMenu);
const changeSelection = (catId, itemId, value) => {
setSelectionMenu((prevSelectionMenu) =>
prevSelectionMenu.map((item) => {
if (item._id_type === catId) {
return {
...item,
plants: item.plants.map((plant) => {
if (plant._id === itemId) {
return { ...plant, selected: !plant.selected };
}
return plant;
})
};
}
return item;
})
);
};
return (
<div>
{selectionMenu.map((item) => (
<Category
{...item}
changeSelection={changeSelection}
key={item._id_type}
/>
))}
</div>
);
}
ReactDOM.render(<App />, document.querySelector('.react'));
<script crossorigin src="https://unpkg.com/react#16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
<div class='react'></div>

customise ant design's table search function so numeric search will return less than or greater than, not only equals

As far as I can see ant design's table currently doesn't ship with a specific numeric search, where I can return results within a specific range, example >10 or <=50.
Given the below example:
codesandbox
import React from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import './index.css';
import { Table, Input, Button, Icon } from 'antd';
import Highlighter from 'react-highlight-words';
const data = [
{
key: '1',
name: 'John Brown',
age: 32,
address: 'New York No. 1 Lake Park',
},
{
key: '2',
name: 'Joe Black',
age: 42,
address: 'London No. 1 Lake Park',
},
{
key: '3',
name: 'Jim Green',
age: 32,
address: 'Sidney No. 1 Lake Park',
},
{
key: '4',
name: 'Jim Red',
age: 32,
address: 'London No. 2 Lake Park',
},
];
class App extends React.Component {
state = {
searchText: '',
};
getColumnSearchProps = dataIndex => ({
filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters }) => (
<div style={{ padding: 8 }}>
<Input
ref={node => {
this.searchInput = node;
}}
placeholder={`Search ${dataIndex}`}
value={selectedKeys[0]}
onChange={e => setSelectedKeys(e.target.value ? [e.target.value] : [])}
onPressEnter={() => this.handleSearch(selectedKeys, confirm)}
style={{ width: 188, marginBottom: 8, display: 'block' }}
/>
<Button
type="primary"
onClick={() => this.handleSearch(selectedKeys, confirm)}
icon="search"
size="small"
style={{ width: 90, marginRight: 8 }}
>
Search
</Button>
<Button onClick={() => this.handleReset(clearFilters)} size="small" style={{ width: 90 }}>
Reset
</Button>
</div>
),
filterIcon: filtered => (
<Icon type="search" style={{ color: filtered ? '#1890ff' : undefined }} />
),
onFilter: (value, record) =>
record[dataIndex]
.toString()
.toLowerCase()
.includes(value.toLowerCase()),
onFilterDropdownVisibleChange: visible => {
if (visible) {
setTimeout(() => this.searchInput.select());
}
},
render: text => (
<Highlighter
highlightStyle={{ backgroundColor: '#ffc069', padding: 0 }}
searchWords={[this.state.searchText]}
autoEscape
textToHighlight={text.toString()}
/>
),
});
handleSearch = (selectedKeys, confirm) => {
confirm();
console.log(selectedKeys);
this.setState({ searchText: selectedKeys[0] });
};
handleReset = clearFilters => {
clearFilters();
this.setState({ searchText: '' });
};
render() {
const columns = [
{
title: 'Name',
dataIndex: 'name',
key: 'name',
width: '30%',
...this.getColumnSearchProps('name'),
},
{
title: 'Age',
dataIndex: 'age',
key: 'age',
width: '20%',
...this.getColumnSearchProps('age'),
},
{
title: 'Address',
dataIndex: 'address',
key: 'address',
...this.getColumnSearchProps('address'),
},
];
return <Table columns={columns} dataSource={data} />;
}
}
ReactDOM.render(<App />, document.getElementById('container'));
Let's look at the age column, if we specify an exact age, exact results will be returned. On the input element when the value is keyed in, on either enter press or onClick, handleSearch is triggered, handleSearch then sets the react state, then the component is re-rendered, all basic react functionality.
I am unsure where is the logic that sets what supposed to be returned so unsure where and how should I implement custom logic to check for a specific range of numbers rather than an exact number. Any ideas?
Alternatively, I checked if a numeric search/filter already exists for ant-design, but I couldn't find anything.
For further reference, see ant-designs table documentation
You can render whatever filter you like, for example using Slider and InputNumber combination:
filterDropdown: ({ setSelectedKeys, selectedKeys, confirm }) => (
<div style={{ padding: 8 }}>
<Row
type="flex"
gutter={10}
style={{ marginBottom: 8, alignItems: "center" }}
>
<Col>Range:</Col>
<Col>
<InputNumber
value={this.state.left}
onChange={e => {
this.setState({ left: e });
setSelectedKeys(data.filter(d => e <= d.age).map(d => d.key));
}}
/>
</Col>
<Col>
<InputNumber
value={this.state.right}
onChange={e => {
this.setState({ right: e });
setSelectedKeys(data.filter(d => d.age <= e).map(d => d.key));
}}
/>
</Col>
</Row>
<Row>
<Slider
range
value={[this.state.left, this.state.right]}
onChange={e => this.setState({ left: e[0], right: e[1] })}
/>
</Row>
<Row>
<Button
type="primary"
block
size="small"
onClick={() => {
this.handleSearchAge(selectedKeys, confirm);
setSelectedKeys(
data
.filter(
d => this.state.left <= d.age && d.age <= this.state.right
)
.map(d => d.key)
);
}}
>
Confirm
</Button>
</Row>
</div>
);
i wonder if you still have the example, the link is broke

Map with bootstrap columns

I'm using map to iterate throug a list of elements, what I want is to have 4 elements per row. This is my render part of the class:
render() {
return (
<div>
<h1>Card List</h1>
{this.props.items ? this.props.items.map((item) =>
<div class="cardSection">
<Row className="show-grid">
<Card name={item.name} imgGold={item.imgGold} />
</Row>
</div>
) : <div>Loading!</div>}
</div>
)
}
}
I want 4 Card components per row using xs={4} md={4}
You can do something like
const items = [
{ name: "1" },
{ name: "2" },
{ name: "3" },
{ name: "4" },
{ name: "5" },
{ name: "6" },
{ name: "7" },
{ name: "8" },
{ name: "9" },
{ name: "10" },
{ name: "11" },
];
const App = () => {
const result = items.map((x,i) => {
return i % 4 === 0 ? items.slice(i, i+4) : null;
}).filter(x => x != null);
return (
<div>
{result.map((result, index) => {
return (<section key={index}>
{result.map(item => <span>{item.name}</span>)}
</section>);
})}
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
span {
margin-left: 5px;
margin-right: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
This will group your item array into groups of 4. You can even make it accept any number you want.
You can then iterate and render each of them in groups of 4.
Please make sure you run the snippet so you can see it working.

Categories