Filling React JS dropdowns from Json data - javascript

I have some json data that looks like this:
{
"author1": {
"books": [{
"title": "title1"
},
{
"title": "title2"
}
],
"movies": [{
"title": "movie1"
},
{
"title": "movie2"
}
]
}
}
I want to have a dropdown that is populated with the authors (like author1). When that dropdown is selected, I then want to populate another dropdown with the keys for that author (books and movies).
So. if my json is in a variable named data, I want to populate the first dropdown with data.keys() and then the second with data[author].keys() where author is the value selected in the first dropdown.
I have seen a lot of examples of populating with json, but not with the keys. I am very new to React JS, so I am not sure how to do this.
Thanks

you can use the following flow.
const AuthorData = ({ symtomsData }) => {
const [data] = useState({
author1: {
books: [
{
title: "title1"
},
{
title: "title2"
}
],
movies: [
{
title: "movie1"
},
{
title: "movie2"
}
]
},
author2: {
books: [
{
title: "titleasd"
},
{
title: "titleqweqw"
}
],
movies: [
{
title: "movieqwewq"
},
{
title: "movieqweqwe"
}
]
}
});
const [authorWroks, setAuthorWorks] = useState({});
const [selectedData, setSelectedData] = useState([]);
const onChangeAuthor = useCallback(
(e) => {
const authorSelected = e.target.value;
if (authorSelected) {
setAuthorWorks(data[authorSelected]);
} else {
setAuthorWorks([]);
}
},
[data]
);
const changeItem = useCallback(
(e) => {
const itemSelected = e.target.value;
console.log("itemSelected", itemSelected);
if (itemSelected) {
console.log("authorWroks", authorWroks[itemSelected]);
setSelectedData(authorWroks[itemSelected]);
} else {
setSelectedData([]);
}
},
[authorWroks]
);
return (
<Grid>
<Col>
<select onChange={onChangeAuthor}>
<option value="">select</option>
{Object.keys(data).map((key, i) => (
<option value={key}>{key}</option>
))}
</select>
<br />
<div>
{Object.keys(authorWroks).length ? (
<select onChange={changeItem}>
<option value="">select</option>
{Object.keys(authorWroks || []).map((key, i) => (
<option onChange={changeItem} value={key}>
{key}
</option>
))}
</select>
) : undefined}
</div>
<div>
{selectedData.length ? (
<select>
<option value="">select</option>
{(selectedData || []).map((data, i) => (
<option onChange={changeItem} value={data.title}>
{data.title}
</option>
))}
</select>
) : undefined}
</div>
</Col>
</Grid>
);
};

Related

How to use drag and drop in ant design?

What I want is an example about how to make the drag and drop of my Table that works properly, but I cannot figure out how to make it works in (functional components)
My code :
function Preview() {
const { name } = useParams();
const [fieldsOfForm, setFieldsOfForm] = useState([]);
const [selectedForm, setSelectedForm] = useState([]);
const columns = [
{
title: 'Posição',
dataIndex: 'pos',
width: 30,
className: 'drag-visible',
render: () =>
<MenuOutlined style={{ cursor: 'grab', color: '#999' }}/>
},
{
title: "Form Name",
dataIndex: "field",
key: "field",
render: (text) => <a>{text}</a>,
},
{
title: "Tipo",
dataIndex: "fieldtype",
key: "fieldtype",
},
];
useEffect(() => {
let mounted = true;
let loadingStates = loading;
if (mounted) {
setFieldsOfForm(location.state);
loadingStates.allFields = false;
setLoading(false);
}
return () => (mounted = false);
}, [selectedForm]);
return (
//Some jsx....
<Row gutter={1}>
<Col span={1}></Col>
<Table dataSource={fieldsOfForm}
columns= {columns}/>
</Row>
// More jsx...
);
}
export default Preview;
Everything that I found on internet about this drag and drop from the lib of antd is in class component , but I wanted to make it works in my functional one.
Example that I found :
multi row drag-able table (antd)
I want some example in function component if someone has tried it already and could help me ?
Here's a functional working example:
import React from "react";
import "antd/dist/antd.css";
import { Table } from "antd";
import {
sortableContainer,
sortableElement,
sortableHandle
} from "react-sortable-hoc";
import { MenuOutlined } from "#ant-design/icons";
const data = [
{
key: "1",
name: "John Brown",
age: 32,
address: "New York No. 1 Lake Park",
index: 0
},
{
key: "2",
name: "Jim Green",
age: 42,
address: "London No. 1 Lake Park",
index: 1
},
{
key: "3",
name: "Joe Black",
age: 32,
address: "Sidney No. 1 Lake Park",
index: 2
},
{
key: "4",
name: "4",
age: 32,
address: "New York No. 1 Lake Park",
index: 3
},
{
key: "5",
name: "5",
age: 42,
address: "London No. 1 Lake Park",
index: 4
},
{
key: "6",
name: "6",
age: 32,
address: "Sidney No. 1 Lake Park",
index: 5
}
];
const DragHandle = sortableHandle(({ active }) => (
<MenuOutlined style={{ cursor: "grab", color: active ? "blue" : "#999" }} />
));
const SortableItem = sortableElement((props) => <tr {...props} />);
const SortableContainer = sortableContainer((props) => <tbody {...props} />);
function SortableTable() {
const [dataSource, setDataSource] = React.useState(data);
const [selectedItems, setSelectedItems] = React.useState([]);
const getColumns = () => {
return [
{
title: "Sort",
dataIndex: "",
width: 30,
className: "drag-visible",
render: (d, dd, i) => (
<>
<DragHandle active={selectedItems.includes(i)} />
</>
)
},
{
title: "Name",
dataIndex: "name",
className: "drag-visible"
},
{
title: "Age",
dataIndex: "age"
},
{
title: "Address",
dataIndex: "address"
}
];
};
const merge = (a, b, i = 0) => {
let aa = [...a];
return [...a.slice(0, i), ...b, ...aa.slice(i, aa.length)];
};
const onSortEnd = ({ oldIndex, newIndex }) => {
let tempDataSource = dataSource;
if (oldIndex !== newIndex) {
if (!selectedItems.length) {
let movingItem = tempDataSource[oldIndex];
tempDataSource.splice(oldIndex, 1);
tempDataSource = merge(tempDataSource, [movingItem], newIndex);
} else {
let filteredItems = [];
selectedItems.forEach((d) => {
filteredItems.push(tempDataSource[d]);
});
let newData = [];
tempDataSource.forEach((d, i) => {
if (!selectedItems.includes(i)) {
newData.push(d);
}
});
tempDataSource = [...newData];
tempDataSource = merge(tempDataSource, filteredItems, newIndex);
}
setDataSource(tempDataSource);
setSelectedItems([]);
}
};
const DraggableContainer = (props) => (
<SortableContainer
useDragHandle
disableAutoscroll
helperClass="row-dragging"
onSortEnd={onSortEnd}
{...props}
/>
);
const DraggableBodyRow = ({ className, style, ...restProps }) => {
// function findIndex base on Table rowKey props and should always be a right array index
const index = dataSource.findIndex(
(x) => x.index === restProps["data-row-key"]
);
return (
<SortableItem
index={index}
{...restProps}
selected={selectedItems.length}
onClick={(e) => {
if (e.ctrlKey || e.metaKey) {
selectedItems.includes(index)
? selectedItems.splice(selectedItems.indexOf(index), 1)
: selectedItems.push(index);
setSelectedItems(selectedItems);
} else {
setSelectedItems([]);
}
}}
/>
);
};
return (
<>
<h3>"CNTRL + Click" to select multiple items</h3>
<Table
pagination={false}
dataSource={dataSource}
columns={getColumns()}
rowKey="index"
components={{
body: {
wrapper: DraggableContainer,
row: DraggableBodyRow
}
}}
/>
{selectedItems.length ? <>{selectedItems.length} items selected </> : ""}
</>
);
}
You can play with it in Sandbox

Not sure how to rerender chart in the app

Here, this app renders a chart like below-
As you can see there are two sidebars in the below app. I need the same chart to render again in the app. What I mean is that I need two of the chart that's been rendered. I think the chart that's rendered is drawn up with the below code but when I try to repeat the same code it won't render the same chart again.
<div class="divBar">
<canvas id="bar"></canvas>
</div>
As below, I even tried to change the canvas id here to a different id but it still won't rerender the chart -
<div class="divBar">
<canvas id="bar-duplicate"></canvas>
</div>
Below is the full app code-
How would I rerender another chart of the same kind that's showing? I need the second chart to render next to the second sidebar menu.
import React, { Component } from "react";
import { useState, useEffect } from "react";
import { FaBeer } from 'react-icons/fa';
import { Link } from 'react-router-dom';
//import { AiOutlineClose } from 'react-icons/ai';
import "./styles.css";
import { Chart } from "chart.js";
import moment from "moment";
import {BrowserRouter as Router, Switch, Route} from 'react-router-dom';
import { ProSidebar, Menu, MenuItem, SubMenu } from 'react-pro-sidebar';
import 'react-pro-sidebar/dist/css/styles.css';
export default class App extends Component {
constructor(props) {
super(props);
this.levelsArr = [
"11/02/2011",
"12/02/2011",
"13/02/2011",
"14/02/2011",
"15/02/2011",
"16/02/2011",
"17/02/2011",
"18/02/2011"
];
this.chartData = {
dataSet1: Array.from(
{ length: 8 },
() => Math.floor(Math.random() * 590) + 10
),
dataSet2: Array.from(
{ length: 8 },
() => Math.floor(Math.random() * 590) + 10
)
};
this.state = {
months: [
{ month: "Jan", value: "0" },
{ month: "Feb", value: "1" },
{ month: "Mar", value: "2" },
{ month: "Apr", value: "3" },
{ month: "May", value: "4" },
{ month: "Jun", value: "5" },
{ month: "Jul", value: "6" },
{ month: "Aug", value: "7" }
],
dates: [
{ date: "11/02/2011", value: "0" },
{ date: "12/02/2011", value: "1" },
{ date: "13/02/2011", value: "2" },
{ date: "14/02/2011", value: "3" },
{ date: "15/02/2011", value: "4" },
{ date: "16/02/2011", value: "5" },
{ date: "17/02/2011", value: "6" },
{ date: "18/02/2011", value: "7" }
],
from: "0",
toMonth: "7",
fromDate: "0",
toDate: "7",
filterLimit: 100,
sidebarOpen: true,
sidebar: false
};
this.onSetSidebarOpen = this.onSetSidebarOpen.bind(this);
this.sidebar = this.showSidebar.bind(this);
}
onSetSidebarOpen(open) {
this.setState({ sidebarOpen: open });
}
showSidebar(sidebar) {
this.setState({sidebar: !sidebar});
}
componentDidMount() {
this.barChart = new Chart("bar", {
type: "bar",
options: {
responsive: true,
title: {
display: true,
text: "Student Admission Data"
}
},
data: {
labels: ["11/02/2011", "12/02/2011", "13/02/2011", "14/02/2011", "15/02/2011", "16/02/2011", "17/02/2011", "18/02/2011"],
datasets: [
{
type: "bar",
label: "School 1",
data: this.chartData.dataSet1,
backgroundColor: "rgba(20,200,10,0.4)",
borderColor: "rgba(20,200,10,0.4)",
fill: false
},
{
type: "bar",
label: "School 2",
data: this.chartData.dataSet2,
backgroundColor: "rgba(100,189,200,0.4)",
borderColor: "rgba(100,189,200,0.4)",
fill: false
}
]
}
});
}
applyFilter() {
//console.log(this.chartData.dataSet1);
const value = this.state.filterLimit;
const lessThanOrGreaterThan = this.state.lessThanOrGreaterThan;
console.log(lessThanOrGreaterThan);
this.barChart.data.datasets[0].data = this.chartData.dataSet1;
this.barChart.data.datasets[1].data = this.chartData.dataSet2;
this.barChart.data.datasets.forEach((data, i) => {
if (lessThanOrGreaterThan === "greaterThan") {
this.barChart.data.datasets[i].data = data.data.map((v) => {
if (v >= value) return v;
else return 0;
});
// console.log(">>>>>>>>", this.barChart.data.datasets[i].data);
} else {
this.barChart.data.datasets[i].data = data.data.map((v) => {
if (v <= value) return v;
else return 0;
});
//console.log("?????????", this.barChart.data.datasets[i].data);
}
});
this.barChart.update();
}
applyDateFilter() {
this.barChart.data.labels = this.levelsArr.slice(
parseInt(this.state.from),
parseInt(this.state.toMonth) + 1
);
this.barChart.update();
}
applyDaysFilter() {
this.barChart.data.labels = this.levelsArr.slice(
parseInt(this.state.fromDate),
parseInt(this.state.toDate) + 1
);
this.barChart.update();
}
render() {
return (
<div class="chart-diplay">
<div>
<React.StrictMode>
<div className = 'container'>
<div class="divSideBar">
<ProSidebar>
<Menu iconShape="square">
<MenuItem>
<select
id="lessThanOrGreaterThan"
value={this.state.lessThanOrGreaterThan}
onChange={(e) =>
this.setState({ lessThanOrGreaterThan: e.currentTarget.value })
}
>
<option value="lessThan">Less Than</option>
<option value="greaterThan">Greater Than</option>
</select>
</MenuItem>
<MenuItem>
<input
id="filterLimit"
placeholder="Filter Limit"
value={this.state.filterLimit}
onChange={(e) => this.setState({ filterLimit: e.target.value })}
></input>
</MenuItem>
<MenuItem>
<button class="button" onClick={() => this.applyFilter()}>
Apply Filter
</button>
</MenuItem>
<MenuItem>
<div>
<select
id="from"
value={this.state.from}
onChange={(e) => this.setState({ from: e.target.value })}
>
{this.state.months.map((el) => (
<option value={el.value} key={el}>
{" "}
{el.month}{" "}
</option>
))}
</select>
<select
id="toMonth"
value={this.state.toMonth}
onChange={(e) => this.setState({ toMonth: e.target.value })}
>
{this.state.months.map((el) => (
<option value={el.value} key={el}>
{" "}
{el.month}{" "}
</option>
))}
</select>
</div>
</MenuItem>
<MenuItem>
<button class="button" onClick={() => this.applyDateFilter()}>
Apply Months Filter
</button>
</MenuItem>
</Menu>
</ProSidebar>
</div>
<div class="divBar">
<canvas id="bar"></canvas>
</div>
</div>
</React.StrictMode>
</div>
<div>
<React.StrictMode>
<div className = 'containerTwo'>
<div class="divSideBar">
<ProSidebar>
<Menu iconShape="square">
<MenuItem>
<select
id="lessThanOrGreaterThan"
value={this.state.lessThanOrGreaterThan}
onChange={(e) =>
this.setState({ lessThanOrGreaterThan: e.currentTarget.value })
}
>
<option value="lessThan">Less Than</option>
<option value="greaterThan">Greater Than</option>
</select>
</MenuItem>
<MenuItem>
<input
id="filterLimit"
placeholder="Filter Limit"
value={this.state.filterLimit}
onChange={(e) => this.setState({ filterLimit: e.target.value })}
></input>
</MenuItem>
<MenuItem>
<button class="button" onClick={() => this.applyFilter()}>
Apply Filter
</button>
</MenuItem>
<MenuItem>
<div>
<select
id="from"
value={this.state.fromDate}
onChange={(e) => this.setState({ fromDate: e.target.value })}
>
{this.state.dates.map((el) => (
<option value={el.value} key={el}>
{" "}
{el.date}{" "}
</option>
))}
</select>
<select
id="toMonth"
value={this.state.toDate}
onChange={(e) => this.setState({ toDate: e.target.value })}
>
{this.state.dates.map((el) => (
<option value={el.value} key={el}>
{" "}
{el.date}{" "}
</option>
))}
</select>
</div>
<MenuItem>
<button class="button" onClick={() => this.applyDaysFilter()}>
Apply Days Filter
</button>
</MenuItem>
</MenuItem>
</Menu>
</ProSidebar>
</div>
</div>
</React.StrictMode>
</div>
</div>
);
}
}
Check this
create two chart object
two canvas element will render
on filter update you need to update your chart object and called update function

React change parent array properties

In the parent component manage-categories.jsx I have an array declared categoryTypes
const categoryTypes = [
{ name: "category", values: props.categories, active: true },
{ name: "type", values: props.types },
{ name: "finish", values: props.finishes },
{ name: "profile", values: props.profiles },
{ name: "thickness", values: props.thicknesses },
{ name: "ral", values: props.rals },
];
and a function selectItem that is called in the child component category-types-card.jsx
const selectItem = (item, category) => {
switch (category.name) {
case "category":
setSelectedCategoryItem(item);
break;
case "type":
setSelectedTypeItem(item);
break;
case "finish":
setSelectedFinishItem(item);
break;
case "profile":
setSelectedProfileItem(item);
break;
case "thickness":
setSelectedThicknessItem(item);
break;
case "ral":
setSelectedRalItem(item);
}
};
In the child component I need to show something for the categories that have active: true Category becomes active when it has an selectedItem.
I tried to make it active like categoryTypes[1] = { ...categoryTypes[1], active: true }; in the above switch, but in the child component the active property does not change for the certain category.
Calling the child component:
<Row className="mb-4">
{categoryTypes.map((category, index) => {
return (
<Colxx
xxs="12"
xs="6"
sm="6"
md="6"
lg="4"
xl="4"
xxl="4"
key={index}
>
<CategoryTypes
category={category}
employee={employee}
selectItem={selectItem}
selectedCategoryItem={selectedCategoryItem}
selectedTypeItem={selectedTypeItem}
selectedFinishItem={selectedFinishItem}
selectedProfileItem={selectedProfileItem}
selectedThicknessItem={selectedThicknessItem}
selectedRalItem={selectedRalItem}
/>
</Colxx>
);
})}
</Row>
How should I handle correctly this situation?
Thanks in advance!
How about passing a callback to the child component? Like so:
const ManageCategories = (props) => {
const [categoryTypes, setCategoryTypes] = useState([
{ name: "category", values: props.categories, active: true },
{ name: "type", values: props.types },
{ name: "finish", values: props.finishes },
{ name: "profile", values: props.profiles },
{ name: "thickness", values: props.thicknesses },
{ name: "ral", values: props.rals },
])
const setCategoryTypeActive = (categoryName, active) => {
setCategoryTypes((categoryTypes) =>
categoryTypes.map((categoryType) =>
categoryType.name === categoryName
? { ...categoryType, active }
: categoryType
)
)
}
return (
<Row className="mb-4">
{categoryTypes.map((category, index) => (
<Colxx xxs="12" xs="6" sm="6" md="6" lg="4" xl="4" xxl="4" key={index}>
<CategoryTypes
category={category}
employee={employee}
selectItem={selectItem}
selectedCategoryItem={selectedCategoryItem}
selectedTypeItem={selectedTypeItem}
selectedFinishItem={selectedFinishItem}
selectedProfileItem={selectedProfileItem}
selectedThicknessItem={selectedThicknessItem}
selectedRalItem={selectedRalItem}
setCategoryTypeActive={setCategoryTypeActive}
/>
</Colxx>
))}
</Row>
)
}
Then, somewhere in your child component, for example:
const CategoryTypesCard = (props) => {
props.setCategoryTypeActive("finish", true)
// ...
}

how to display json data in dropdown using reactj

i need to display data in dropdown i haven given json data with code.
this.setState({
data : [
{id:1,type:A},
{id:1,type:B},
{id:1,type:C},
]
})
<select className="form-control" onChange={(e) => this.handleChange(e)} >
<option >Select data</option>
{
this.state.data.map((i, h) =>
(<option key={h} value={i.type}>{i.type}</option>))
}
</select>
Json isn't correct...put quotation for string type value-"A", "B", "C"
data: [{ id: 1, type: "A" }, { id: 1, type: "B" }, { id: 1, type: "C" }]
JSX
class App extends Component {
state = {
data: [{ id: 1, type: "A" }, { id: 1, type: "B" }, { id: 1, type: "C" }]
};
handleChange = e => {
console.log(e.target.value);
};
render() {
return (
<div>
<select className="form-control" onChange={this.handleChange}>
<option>Select data</option>
{this.state.data.map((i, h) => (
<option key={h} value={i.type}>
{i.type}
</option>
))}
</select>
</div>
);
}
}

Attempting to show array element of react select in list item

I am using react-select to store multiple elements and am using the map function to display elements which is working fine. But when I am using the same element in another class to display in a list element it shows a blank.
Here is the code where I am displaying the multiple options.
const Departments = [
{ label: "OneIT", value: "OneIT" },
{ label: "HR", value: "HR" },
{ label: "Vigilance", value: "Vigilance" },
{ label: "Ethics", value: "Ethics" },
{ label: "Corporate Services", value: "Corporate Services" },
{ label: "Legal", value: "Legal" },
{ label: "Sports", value: "Sports" },
{ label: "TQM", value: "TQM" },
{ label: "Iron Making", value: "Iron Making" },
{ label: "TMH", value: "TMH" }
];
class MultiSelect2 extends Component {
state = {
selectedOptions: []
};
handleChangeField = selectedOptions => {
this.setState({ selectedOptions });
};
render() {
const { selectedOption } = this.state;
return (
<div className="container">
<div className="row">
<div className="col-md-2"></div>
<div className="col-md-8">
<span>Select Department</span>
<Select
value={selectedOption}
options={Departments}
onChange={this.handleChangeField}
isMulti
/>
{this.state.selectedOptions.map(o => (
<p>{o.value}</p>
))}
</div>
<div className="col-md-4"></div>
</div>
</div>
);
}
}
I am trying to display this in another class in the list item but it is not showing.
export class Confirm extends Component {
state = {
selectedOptions: []
};
render() {
const {
values: {selectedOptions
}
} = this.props;
return (
<List>
<ListItemText primary="Departments" secondary={selectedOptions} />
</List>

Categories

Resources