Add to cart function using react - javascript

I am building a search filter of sorts using Elasticsearch and ReactiveSearch for UI.
Each result has an ID, title, etc that I can call to display it when a user searches. I need a button for each results, and when the user clicks it, it should 'add to cart' or something like that. I just need the clicked results to be shown in the next page.
The code below is my search field, and the results that are shown. I have an onclick function, but I don't know how to proceed after that. I think I need to use redux.
class Results extends Component {
render() {
return (
<ReactiveBase
app="datataglist"
credentials="mRgWyoKGQ:f47be2a6-65d0-43b6-8aba-95dbd49eb882"
url="https://scalr.api.appbase.io"
>
<DataSearch
componentId="search"
dataField={[
"maker_tag_name",
"maker_tag_name.autosuggest",
"maker_tag_name.keyword"
]}
fieldWeights={[6, 2, 6]}
fuzziness={1}
highlightField={["maker_tag_name"]}
placeholder="Search Tag Name"
style={{
marginBottom: 20
}}
title="Maker Tag Name"
/>
<SelectedFilters />
<ReactiveList
componentId="results"
dataField="_score"
pagination={true}
react={{
and: ["system", "grouping", "unit", "search"]
}}
size={10}
noResults="No results were found..."
renderItem={renderItem}
/>
</ReactiveBase>
);
}
}
function getNestedValue(obj, path) {
const keys = path.split(".");
const currentObject = obj;
const nestedValue = keys.reduce((value, key) => {
if (value) {
return value[key];
}
return "";
}, currentObject);
if (typeof nestedValue === "object") {
return JSON.stringify(nestedValue);
}
return nestedValue;
}
function renderItem(res, triggerClickAnalytics) {
let { url, unit, title, system, score, proposed, id } = {
title: "maker_tag_name",
proposed: "proposed_standard_format",
unit: "units",
system: "system",
score: "_score",
url: "",
id: "_id"
};
title = getNestedValue(res, title);
system = getNestedValue(res, system);
url = getNestedValue(res, url);
unit = getNestedValue(res, unit);
score = getNestedValue(res, score);
proposed = getNestedValue(res, proposed);
id = getNestedValue(res, id);
return (
<Row
onClick={triggerClickAnalytics}
type="flex"
gutter={16}
key={res._id}
style={{ margin: "20px auto", borderBottom: "1px solid #ededed" }}
>
<Col style={{ width: "360px" }}>
<h3
style={{ fontWeight: "600" }}
dangerouslySetInnerHTML={{
__html: title || "Choose a valid Title Field"
}}
/>
</Col>
<div style={{ padding: "20px" }} />
<Col>
<p
style={{ fontSize: "1em", width: "300px" }}
dangerouslySetInnerHTML={{
__html: system || "Choose a valid Description Field"
}}
/>
</Col>
<div style={{ padding: "10px" }} />
<Col>
<p
style={{ fontSize: "1em" }}
dangerouslySetInnerHTML={{
__html: unit || "-"
}}
/>
</Col>
<div style={{ padding: "10px" }} />
<Col style={{ minWidth: "120px" }}>
<p
style={{ fontSize: "1em", width: "300px"}}
dangerouslySetInnerHTML={{
__html: proposed || "Choose a valid Description Field"
}}
/>
</Col>
<div style={{ padding: "10px" }} />
<Col>
<p
style={{ fontSize: "1em"}}
dangerouslySetInnerHTML={{
__html: Math.round(score) || "Choose a valid Description Field"
}}
/>
</Col>
<Col>
<Button
shape="circle"
icon={<CheckOutlined />}
style={{ marginRight: "5px" }}
onClick={()=>{this.handleClick(id)}}
/>
</Col>
<Col style={{ minWidth: "120px" }}>
<p
style={{ fontSize: "1em", width: "300px"}}
dangerouslySetInnerHTML={{
__html: id || "Choose a valid Description Field"
}}
/>
</Col>
</Row>
);
}
export default Results;
Any help would be appreciated.

Related

unable to use MaterialUI Datepicker,Dayjs with useFormik and Yup

I am using Material UI Date picker with day js,but the issue that arising again and again is,'when I select the date on calender,1st time it updates in textfield and then it is not working.And also having problem in Yup like when touched 1st time it gives error means works perfectly but when removing the date from text field and left the field blank it does not work.'
codesandbox Link : https://codesandbox.io/s/material-ui-datepicker-error-pdvt07
code:
import "./styles.css";
import React, { useState } from "react";
import {
TextField,
Container,
Typography,
Stack,
Button,
Box
} from "#mui/material";
import { Link } from "react-router-dom";
import { Helmet } from "react-helmet-async";
import { styled } from "#mui/material/styles";
import { AdapterDayjs } from "#mui/x-date-pickers/AdapterDayjs";
import { DatePicker } from "#mui/x-date-pickers/DatePicker";
import { DesktopDatePicker } from "#mui/x-date-pickers/DesktopDatePicker";
import TodayIcon from "#mui/icons-material/Today";
import moment from "moment";
import dayjs from "dayjs";
import { LocalizationProvider } from "#mui/x-date-pickers/LocalizationProvider";
import InputAdornment from "#mui/material/InputAdornment";
import Autocomplete from "react-google-autocomplete";
import { useFormik } from "formik";
import * as Yup from "yup";
// import useResponsive from "../../hooks/useResponsive";
export default function App() {
// const navigate = useNavigate();
const validationSchema = Yup.object().shape({
firstName: Yup.string().required("First Name is required"),
lastName: Yup.string()
// .length(3, 'Last Name must be greater than 3 characters')
.required("Last Name is required"),
email: Yup.string()
.email("Invalid email")
.required("Please enter your email"),
mobile: Yup.string()
.length(10, "Mobile Number must be 10 digit")
.required("Mobile Number is required"),
dob: Yup.string().required("Dob is required"),
passingYear: Yup.string().required("Passing out year is required"),
location: Yup.string().required("Location is required"),
occupation: Yup.string().required("Occupation is required"),
address: Yup.string().required("Addres is required")
});
const formik = useFormik({
initialValues: {
firstName: "",
lastName: "",
email: "",
mobile: "",
dob: "",
passingYear: "",
location: "",
address: "",
occupation: ""
},
validationSchema,
onSubmit: (values) => {
console.log(values);
// navigate(`/verify-otp?email=${values.email}`, { replace: true });
}
});
return (
<div className="App">
<form onSubmit={formik.handleSubmit}>
<Stack direction={"column"} spacing={3}>
<Box>
<TextField
sx={{
width: "100%"
}}
id="outlined-firstName-input"
label="First Name"
name="firstName"
type={"text"}
onChange={formik.handleChange}
value={formik.values.firstName}
onBlur={formik.handleBlur}
autoComplete="off"
/>
{formik.touched.firstName && formik.errors.firstName && (
<p
style={{
color: "red",
marginTop: "5px",
marginBottom: "-15px"
}}
>
{formik.errors.firstName}
</p>
)}
</Box>
<Box>
<TextField
sx={{
width: "100%"
}}
id="outlined-lastName-input"
label="Last Name"
name="lastName"
type={"text"}
onChange={formik.handleChange}
value={formik.values.lastName}
onBlur={formik.handleBlur}
autoComplete="off"
/>
{formik.touched.lastName && formik.errors.lastName && (
<p
style={{
color: "red",
marginTop: "5px",
marginBottom: "-15px"
}}
>
{formik.errors.lastName}
</p>
)}
</Box>
<Box>
<TextField
sx={{
width: "100%"
}}
id="outlined-email-input"
label="Email address"
name="email"
type={"email"}
onChange={formik.handleChange}
value={formik.values.email}
onBlur={formik.handleBlur}
/>
{formik.touched.email && formik.errors.email && (
<p
style={{
color: "red",
marginTop: "5px",
marginBottom: "-15px"
}}
>
{formik.errors.email}
</p>
)}
</Box>
<Box>
<TextField
sx={{
width: "100%"
}}
InputProps={{
startAdornment: (
<InputAdornment position="start">+91</InputAdornment>
)
}}
id="outlined-mobile-input"
label="Mobile Number"
type="tel"
name="mobile"
onChange={formik.handleChange}
value={formik.values.mobile}
onBlur={formik.handleBlur}
autoComplete="off"
/>
{formik.touched.mobile && formik.errors.mobile && (
<p
style={{
color: "red",
marginTop: "5px",
marginBottom: "-15px"
}}
>
{formik.errors.mobile}
</p>
)}
</Box>
<Box
sx={{
width: "100%"
}}
>
<LocalizationProvider dateAdapter={AdapterDayjs}>
<DesktopDatePicker
label="Date of birth"
inputFormat="DD/MM/YYYY"
value={dayjs(formik.values?.dob).format("DD-MM-YYYY") || ""}
onChange={(newValue) => {
formik.setFieldValue(
"dob",
dayjs(newValue).format("DD-MM-YYYY")
);
formik.setFieldTouched("dob", true);
}}
renderInput={(params) => (
<TextField
sx={{
width: "100%"
}}
{...params}
name="dob"
onBlur={formik.handleBlur}
error={formik.errors.dob && formik.touched.dob}
/>
)}
/>
</LocalizationProvider>
{formik.touched.dob && formik.errors.dob && (
<p
style={{
color: "red",
marginTop: "5px",
marginBottom: "-15px"
}}
>
{formik.errors.dob}
</p>
)}
</Box>
<Box
sx={{
width: "100%"
}}
>
<LocalizationProvider dateAdapter={AdapterDayjs}>
<DatePicker
views={["year"]}
label="Passing year"
maxDate={dayjs().subtract(1, "year")}
value={formik.values.passingYear || ""}
onBlur={formik.handleBlur}
onChange={(newValue) => {
formik.setFieldValue("passingYear", newValue?.format("YYYY"));
}}
renderInput={(params) => (
<TextField
sx={{
width: "100%"
}}
{...params}
name="passingYear"
onBlur={formik.handleBlur}
error={
formik.errors.passingYear && formik.touched.passingYear
}
/>
)}
/>
{formik.touched.passingYear && formik.errors.passingYear && (
<p
style={{
color: "red",
marginTop: "5px",
marginBottom: "-15px"
}}
>
{formik.errors.passingYear}
</p>
)}
</LocalizationProvider>
</Box>
<Box>
<TextField
sx={{
width: "100%"
}}
id="outlined-occupation-input"
label="Occupation"
name="occupation"
type={"text"}
onChange={formik.handleChange}
value={formik.values.occupation}
onBlur={formik.handleBlur}
autoComplete="off"
/>
{formik.touched.occupation && formik.errors.occupation && (
<p
style={{
color: "red",
marginTop: "5px",
marginBottom: "-15px"
}}
>
{formik.errors.occupation}
</p>
)}
</Box>
<Box>
<Autocomplete
className="location"
style={{
width: "100%",
paddingLeft: "13px",
height: "8vh",
border: "1px solid rgb(224,224,224)",
borderRadius: "6px",
fontSize: "17px",
fontWeight: "500",
color: "#212B36",
backgroundColor: "#F9FAFB",
"&:focus": {
borderWidth: "2px",
borderColor: "darken(#2f8f1f, 5%)",
fontSize: "20px"
}
}}
apiKey={"AIzaSyABX4LTqTLQGg_b3jFOH8Z6_H5CDqn8tbc"}
onPlaceSelected={(place) => {
formik.setFieldValue("location", place?.formatted_address);
}}
types={["address"]}
componentRestrictions={{ country: "us" }}
name="location"
onChange={formik.handleChange}
onBlur={formik.handleBlur}
/>
{formik.touched.location && formik.errors.location && (
<p
style={{
color: "red",
marginTop: "5px",
marginBottom: "-15px"
}}
>
{formik.errors.location}
</p>
)}
</Box>
<Box
sx={{
width: "100%"
}}
>
<TextField
sx={{
width: "100%"
}}
id="outlined-password-input"
label="Addres"
name="address"
value={formik.values.address}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
type="text"
multiline
rows={4}
maxRows={6}
autoComplete="off"
/>
{formik.touched.address && formik.errors.address && (
<p
style={{
color: "red",
marginTop: "5px",
marginBottom: "-15px"
}}
>
{formik.errors.address}
</p>
)}
</Box>
<Box ml={"auto"}>
<Button fullWidth size="large" type="submit" variant="contained">
Sign Up
</Button>
</Box>
</Stack>
</form>
</div>
);
}
Thanks in advance.....
you need to use dayjs format when trying to display the date. the date picker already formats the date for you in the textfield.
<DesktopDatePicker
label="Date of birth"
inputFormat="DD/MM/YYYY"
value={formik.values?.dob}
onChange={(newValue) => {
formik.setFieldValue(
"dob",
newValue
);
formik.setFieldTouched("dob", true);
}}
renderInput={(params) => (
<TextField
sx={{
width: "100%"
}}
{...params}
name="dob"
onBlur={formik.handleBlur}
error={formik.errors.dob && formik.touched.dob}
/>
)}
/>

How fetch data from parent element to child component?

Hello Im new in fetching and I have a problem, because I dont know how pass data from one component to child component. In the Fetch.js i have carousel and when I click on actual slide I want to display data in / learn and only ID what i clicked in carousel :(
I dont know exacly how to approach it and hope for help
Fetch.js
import {
Col,
Container,
Row,
Card,
Button,
Form,
Carousel,
} from "react-bootstrap";
import axios from "axios";
import { Link } from "react-router-dom";
export default function Fetch() {
const [posts, setPosts] = useState([]);
const [formData, setFormData] = useState({
USERNAME: "",
LINK_THUMBNAIL: "",
LINK_TITLE: "",
});
useEffect(() => {
fetchData();
}, [posts]);
const fetchData = async () => {
const { data } = await axios.get(
"https://api.test.dokume.net/public.php/object/465?include_data=true",
{
headers: {
"X-DOKUME-API-KEY":
"aJorRrbtlcNfONLWdg2tg0Wz1vEFeOjDhrxygQFUb9mdJSOexoUm6vjSmOt27hvq",
"X-DOKUME-PROFILEID": "21152",
},
}
);
setPosts(data.MESSAGE);
};
const postData = async (e) => {
e.preventDefault();
console.log("form submited");
const { data } = await axios.post(
"https://api.test.dokume.net/public.php/object/465?include_data=true",
formData,
{
headers: {
"X-DOKUME-API-KEY":
"aJorRrbtlcNfONLWdg2tg0Wz1vEFeOjDhrxygQFUb9mdJSOexoUm6vjSmOt27hvq",
"X-DOKUME-PROFILEID": "21152",
},
}
);
console.log("form success");
setFormData({
USERNAME: "",
LINK_THUMBNAIL: "",
LINK_TITLE: "",
});
};
const handleChange = (e) => {
setFormData({ ...formData, [e.target.name]: e.target.value });
};
if (posts.length === 0) {
return <div>Loading data...</div>;
}
return (
<Container
fluid
className="fetch pt-5 bg-light "
style={{ height: "100vh", overflow: "hidden" }}
>
<Row
className="row justify-content-center pt-5 "
style={{
alignItems: "center",
justifyContent: "center",
textAlign: "center",
fontSize: "4vw",
lineHeight: "90%",
fontWeight: "bold",
}}
>
<Col md sm lg className="pt-5">
<h1>Trusted by 25M+</h1>
<Carousel
controls={false}
indicators={false}
style={{
color: "blue",
}}
>
<Carousel.Item>
<h3>Small Business</h3>
</Carousel.Item>
<Carousel.Item>
<h3>Influencers</h3>
</Carousel.Item>
<Carousel.Item>
<h3>Tech Industy</h3>
</Carousel.Item>
</Carousel>
</Col>
</Row>
<Row style={{ justifyContent: "center" }}>
<Col
className="bg-secondary rounded mb-5"
md={3}
sm
lg
xl
style={{
marginLeft: "3rem",
maxHeight: "300px",
marginTop: "3rem",
marginRight: "3rem",
}}
>
<Form onSubmit={postData}>
<Form.Group controlId="formFile" className="mb-3">
<Form.Label>Attach Img URL</Form.Label>
<Form.Control
type="url"
name="LINK_THUMBNAIL"
onChange={handleChange}
value={formData.LINK_THUMBNAIL}
/>
</Form.Group>
<Form.Group className="mb-3" controlId="formBasicEmail">
<Form.Label>Title</Form.Label>
<Form.Control
onChange={handleChange}
type="text"
name="LINK_TITLE"
placeholder="Enter title"
value={formData.LINK_TITLE}
/>
</Form.Group>
<Form.Group className="mb-3" controlId="formBasicPassword">
<Form.Label>Username</Form.Label>
<Form.Control
onChange={handleChange}
type="text"
name="USERNAME"
placeholder="Username"
value={formData.USERNAME}
/>
</Form.Group>
<Button variant="primary" type="submit">
Submit
</Button>
</Form>
</Col>
<Col md={8} sm lg xl className=" mt-5">
<Carousel indicators={false} fade={true} style={{ height: "500px" }}>
{posts.map((item) => (
<Carousel.Item key={item.ID} className="bg-secondary rounded ">
<img
className="d-block rounded pt-5"
src={item.LINK_THUMBNAIL}
alt="First slide"
style={{
height: "300px",
width: "auto",
objectFit: "contain",
padding: "10px",
}}
/>
<Carousel.Caption
key={item.ID}
className="text-dark "
style={{ paddingLeft: "5rem" }}
>
<h3 className="pt-5 ">{item.LINK_TITLE}</h3>
<h3 className="pt-5 ">{item.USERNAME}</h3>
<h3 className="pt-5 ">
<a href={item.LINK_THUMBNAIL}> Link:</a>
</h3>
</Carousel.Caption>
</Carousel.Item>
))}
</Carousel>
</Col>
</Row>
</Container>
);
}
/learn - Learning.js
import React from "react";
import { Container, Row, Col, Card, Button } from "react-bootstrap";
const Learning = () => {
return (
<Container className="bg-secondary pt-5" style={{ height: "100vh" }}>
<Row className="pt-5" style={{ textAlign: "center" }}>
<Col className="pt-5">
<h1>Learn Component</h1>
<p> Tutaj wsadzisz caly fetch w kartach</p>
</Col>
</Row>
<Row
style={{
textAlign: "center",
alignItems: "center",
justifyContent: "center",
}}
>
<Col>
<Card style={{ width: "18rem" }}>
<Card.Img variant="top" />
<Card.Body>
<Card.Title>
<h3>PROFILE_PICTURE:</h3> Click
</Card.Title>
<Card.Text>
<h3>LINK_URL</h3> Click
</Card.Text>
<Card.Text>
<h3>USERNAME</h3> Click
</Card.Text>
<Card.Text>
<h3>STASH_NAME</h3>
Click
</Card.Text>
<Card.Text>
<h3>LINK_THUMBNAIL</h3>
Click
</Card.Text>
<Button variant="primary">Go somewhere</Button>
</Card.Body>
</Card>
</Col>
</Row>
</Container>
);
};
export default Learning;

Cannot read props of undefined

I am trying to add class form control for my select statement. However there is a problem which occurs. It shows props are undefined.
Here is the code:
const useStyles = makeStyles({
root: {
width: "100%",
maxWidth: 500
}
});
const classes = {
formControl: {
margin: this.props.theme.spacing(1),
minWidth: 120,
},
selectEmpty: {
marginTop: this.props.theme.spacing(2),
},
};
export class FormUserDetails extends Component {
constructor(props) {
super(props);
this.state = { KPI: [], addModalShow: false,age: "",
name: "hai" };
}
continue = e => {
e.preventDefault();
if (document.getElementById("Title").value.length < 5) {
document.getElementById("title").style.visibility = "visible";
document.getElementById("Title").style.border = "1px solid red";
// keep form from submitting
} else if (document.getElementById("Details").value.length < 10) {
document.getElementById("details").style.visibility = "visible";
document.getElementById("Details").style.border = "1px solid red";
// keep form from submitting
} else if (document.getElementById("What").value.length < 10) {
document.getElementById("what").style.visibility = "visible";
document.getElementById("What").style.border = "1px solid red";
// keep form from submitting
} else if (document.getElementById("Why").value.length < 10) {
document.getElementById("why").style.visibility = "visible";
document.getElementById("Why").style.border = "1px solid red";
// keep form from submitting
} else if (document.getElementById("How").value.length < 10) {
document.getElementById("how").style.visibility = "visible";
document.getElementById("How").style.border = "1px solid red";
// keep form from submitting
} else if (document.getElementById("Implementation_Status").value == "") {
document.getElementById("status").style.visibility = "visible";
document.getElementById("Status").style.border = "1px solid red";
// keep form from submitting
} else if (document.getElementById("Cost").value.length < 1) {
document.getElementById("cost").style.visibility = "visible";
document.getElementById("Cost").style.border = "1px solid red";
// keep form from submitting
} else if (document.getElementById("Benefits").value.length < 10) {
document.getElementById("benefits").style.visibility = "visible";
document.getElementById("Benefits").style.border = "1px solid red";
// keep form from submitting
} else {
// else form is good let it submit, of course you will
// probably want to alert the user WHAT went wrong.
this.props.nextStep();
}
};
handleSubmit(event) {
event.preventDefault();
fetch("https://localhost:44384/api/Details", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify({
TBD_ID: null,
TBD_TITLE: event.target.Title.value,
TBD_WHAT: event.target.What.value,
TBD_WHY: event.target.Why.value,
TBD_HOW: event.target.How.value,
TBD_STAGE: 1,
TBD_STATUS: event.target.Implementation_Status.value,
TBD_COST: event.target.Cost.value,
TBD_BENEFIT: event.target.Benefits.value,
TBD_BENEFIT_TYPE: 1,
TBD_FL_ACTIVE: null,
TBD_CRT_ID: null,
TBD_CRT_TS: null,
TBD_UPD_ID: null,
TBD_UPD_TS: null,
TBD_VALUE_ID: 2
})
})
.then(res => res.json())
.then(
result => {
alert(result);
},
error => {
alert("Failed");
}
);
}
//1
handleChangeRows = idx => e => {
const { Kpi_Before, value } = e.target;
const rows = [...this.state.rows];
rows[idx] = {
[Kpi_Before]: value
};
this.setState({
rows
});
};
//2
handleAddRow = () => {
const item = {
KPI_Before: "",
UOM_Before: "",
Base_Before: "",
Target_Before: "",
dateTime: ""
};
this.setState({
rows: [...this.state.rows, item]
});
};
//3
handleRemoveRow = () => {
this.setState({
rows: this.state.rows.slice(0, -1)
});
};
render() {
const { values, handleChange } = this.props;
const { deps } = this.state;
let { values1 } = this.state;
let addModalClose = () => this.setState({ addModalShow: false });
return (
<MuiThemeProvider theme={theme}>
<React.Fragment>
<div className={useStyles.root}>
<Grid item xs={12}>
<AppBar position="static">
<Toolbar>
<NavLink to="dashboard">
<DashboardIcon style={{ color: "white" }} />
</NavLink>
<Typography
align="center"
style={{ width: "100%", alignItems: "center" }}
>
Best Practices Management System
</Typography>
</Toolbar>
</AppBar>
</Grid>
</div>
<br />
<Form onSubmit={this.handleSubmit} style={{ marginLeft: "5%" }}>
<Grid container>
<Grid item xs={12}>
<TextField
label="Title"
variant="outlined"
size="small"
name="Title"
id="Title"
placeholder="Enter the Title of the Best Practice"
onChange={handleChange("Title")}
defaultValue={values.Title}
multiline
rows={1}
rowsMax={4}
style={{ width: "95%" }}
/>
<label
id="title"
style={{ visibility: "hidden", color: "red" }}
>
Title must be atleast 5 characters long
</label>
</Grid>
</Grid>
<Grid container>
<Grid item xs={6}>
<TextField
placeholder="Enter the details of the Best Practice"
label="Details of Best Practice"
id="Details"
size="small"
name="Details"
onChange={handleChange("Details")}
defaultValue={values.Details}
style={{ width: "90%" }}
variant="outlined"
multiline
rows={2}
rowsMax={4}
/>
<label
id="details"
style={{ visibility: "hidden", color: "red" }}
>
Details of Best Practice must be atleast 10 characters long
</label>
</Grid>
<Grid item xs={6}>
<TextField
placeholder="What is the Best Practice?"
label="What is the Best Practice"
size="small"
id="What"
name="What"
onChange={handleChange("What")}
defaultValue={values.What}
style={{ width: "90%" }}
variant="outlined"
multiline
rows={2}
rowsMax={4}
/>
<label id="what" style={{ visibility: "hidden", color: "red" }}>
What is the Best Practice must be atleast 10 characters long
</label>
</Grid>
</Grid>
<Grid container>
<Grid item xs={6}>
<TextField
placeholder="Why was the Best Practice Implemented"
label="Why was the Best Practice Implemented"
size="small"
name="Why"
id="Why"
onChange={handleChange("Why")}
defaultValue={values.Why}
style={{ width: "90%" }}
variant="outlined"
multiline
rows={2}
rowsMax={4}
/>
<label id="why" style={{ visibility: "hidden", color: "red" }}>
Why was the Best Practice implemented must be atleast 10
characters long
</label>
</Grid>
<Grid item xs={6}>
<TextField
placeholder="How was the Best Practice Implemented"
label="How was the Best Practice Implemented"
size="small"
name="How"
id="How"
onChange={handleChange("How")}
defaultValue={values.How}
style={{ width: "90%" }}
variant="outlined"
multiline
rows={2}
rowsMax={4}
/>
<label id="how" style={{ visibility: "hidden", color: "red" }}>
How was the Best Practice implemented must be atleast 10
characters long
</label>
</Grid>
</Grid>
<Grid container>
<Grid item xs={6}>
<FormControl id="Status" style={{ width: "90%" }} size="small">
<AddProcessModal
show={this.state.addModalShow}
onHide={addModalClose}
/>
<InputLabel
htmlFor="Implementation_Status"
id="Status"
style={{
marginLeft: 10,
top: "50%",
transform: "translate(0,-50%"
}}
>
Implementation Status
</InputLabel>
<Select
labelId="Implementation_Status"
name="Status"
id="Status"
onChange={handleChange("Status")}
defaultValue={values.Status}
variant="outlined"
inputProps={{
id: "Implementation_Status",
name: "age"
}}
>
<MenuItem value="1">Implemented</MenuItem>
<MenuItem value="2">Implementation in Progress</MenuItem>
<MenuItem value="3">Not Implemented</MenuItem>
</Select>
</FormControl>
<label
id="status"
style={{ visibility: "hidden", color: "red" }}
>
Implementation Status cannot be blank
</label>
</Grid>
<Grid item xs={6}>
<Form.Group controlId="TBD_COST">
<TextField
placeholder="Cost of Implementation of the Best Practice"
label="Cost of Implementation"
name="Cost"
id="Cost"
size="small"
onChange={handleChange("Cost")}
defaultValue={values.Cost}
style={{ width: "90%" }}
variant="outlined"
/>
<label
id="cost"
style={{ visibility: "hidden", color: "red" }}
>
Cost of Implementation cannot be left blank
</label>
</Form.Group>
</Grid>
</Grid>
<Grid container>
<Grid item xs={6}>
<TextField
placeholder="Benefits of the Best Practice"
label="Benefits of the Best Practice"
size="small"
name="Benefits"
id="Benefits"
onChange={handleChange("Benefits")}
defaultValue={values.Benefits}
style={{ width: "90%" }}
variant="outlined"
multiline
rows={2}
rowsMax={4}
/>
<label
id="benefits"
style={{ visibility: "hidden", color: "red" }}
>
Benefits must be at least 10 characters long
</label>
</Grid>
<Grid item xs={6}>
<FormControl className={classes.formControl} id="Process" style={{ width: "78%" }} size="small">
<InputLabel
htmlFor="Process"
id="Process"
style={{
marginLeft: 10,
top: "50%",
transform: "translate(0,-50%"
}}
>
Process
</InputLabel>
<Select
labelId="Process"
name="Process"
id="Process"
value={this.state.Process}
defaultValue={values.Process}
onChange={() => this.setState({ addModalShow: true })}
variant="outlined"
InputLabelProps={{
shrink: this.state.value ? true : false
}}
inputProps={{
name: "Process",
id: "Process"
}}
>
<option aria-label='None' value='' />
<option value={10}>Ten</option>
<option value={20}>Twenty</option>
<option value={30}>Thirty</option>
</Select>
</FormControl>
<Button
variant="outlined"
color="primary"
onClick={() => this.setState({ addModalShow: true })}
size="small"
style={styles.button2}
>
+
</Button>
<label
id="process"
style={{ visibility: "hidden", color: "red" }}
>
Process cannot be blank
</label>
</Grid>
</Grid>
<Grid
direction="row"
justify="right"
alignItems="right"
className="text-right"
style={{ width: "96%" }}
>
<Button
variant="contained"
size="small"
color="primary"
style={styles.button}
onClick={this.continue}
className="float-right"
>
Continue
</Button>
<Button
variant="contained"
size="small"
color="primary"
type="submit"
style={styles.button1}
>
Submit
</Button>
</Grid>
</Form>
</React.Fragment>
</MuiThemeProvider>
);
}
}
const theme = createMuiTheme({
palette: {
primary: blue,
secondary: purple
},
status: {
danger: "orange"
}
});
const styles = {
button: {
align: "right",
margin: 15,
marginRight: "1%"
},
button1: {
align: "right",
margin:15,
marginRight: "1%",
backgroundColor: "#21b6ae"
},
button2: {
margin: 2
}
};
export default FormUserDetails;
You probably dont require the jsx functions but please see what is the issue.
The code in short is this:
const classes = {
formControl: {
margin: this.props.theme.spacing(1),
minWidth: 120,
},
selectEmpty: {
marginTop: this.props.theme.spacing(2),
},
};
The code which I am using just to add the theme but there is an issue with props
In your code, this may point to window object, so it complains props are undefined
Have you tried
import { makeStyles } from '#material-ui/core/styles';
const useStyles = makeStyles((theme) => ({
formControl: {
margin: theme.spacing(1),
minWidth: 120,
},
selectEmpty: {
marginTop: theme.spacing(2),
},
}));
and inside your component
const classes = useStyles();

How to update react state

I have a list of results from my search output. Each result has an onclick function. I want to display each of the results that the user clicks, and for now I can add each result that the user clicks to an array using this function:
let selectedData = []
function addFunc(resultdata){
console.log(resultdata)
selectedData = [...selectedData, resultdata]
console.log(selectedData)
};
I'm new to React, but I know this isn't the right way and I might have to use states or react hooks. The problem is that because I am using Elasticsearch to output the results, my results are in a function, not the main class. Like this:
class Search extends Component {
render() {
return (
<div>
<ReactiveBase
app="datataglist"
credentials="mRgWyoKGQ:f47be2a6-65d0-43b6-8aba-95dbd49eb882"
url="https://scalr.api.appbase.io"
>
<DataSearch
componentId="search"
dataField={[
"maker_tag_name",
"maker_tag_name.autosuggest",
"maker_tag_name.keyword"
]}
fieldWeights={[6, 2, 6]}
fuzziness={1}
highlightField={["maker_tag_name"]}
placeholder="Search Tag Name"
style={{
marginBottom: 20
}}
title="Maker Tag Name"
/>
<Row gutter={16}>
<Col span={8}>
<MultiList
componentId="system"
dataField="system.keyword"
queryFormat="or"
size={100}
sortBy="asc"
style={{
marginBottom: 20
}}
title="System"
/>
</Col>
<Col span={8}>
<MultiList
componentId="grouping"
dataField="grouping.keyword"
size={100}
style={{
marginBottom: 20
}}
title="Grouping"
/>
</Col>
<Col span={8}>
<MultiList
componentId="unit"
dataField="units.keyword"
size={100}
style={{
marginBottom: 20
}}
title="Unit"
/>
</Col>
</Row>
<SelectedFilters />
<ReactiveList
componentId="results"
dataField="_score"
pagination={true}
react={{
and: ["system", "grouping", "unit", "search"]
}}
size={10}
noResults="No results were found..."
renderItem={RenderItem}
/>
</ReactiveBase>
<div>
</div>
</div>
);
}
}
function getNestedValue(obj, path) {
const keys = path.split(".");
const currentObject = obj;
const nestedValue = keys.reduce((value, key) => {
if (value) {
return value[key];
}
return "";
}, currentObject);
if (typeof nestedValue === "object") {
return JSON.stringify(nestedValue);
}
return nestedValue;
}
function RenderItem(res, triggerClickAnalytics) {
let { unit, title, system, score, proposed, id } = {
title: "maker_tag_name",
proposed: "proposed_standard_format",
unit: "units",
system: "system",
score: "_score",
id: "_id"
};
title = getNestedValue(res, title);
system = getNestedValue(res, system);
unit = getNestedValue(res, unit);
score = getNestedValue(res, score);
proposed = getNestedValue(res, proposed);
id = getNestedValue(res, id);
const resultdata = {id, title, system, unit, score, proposed}
return (
<Row
onClick={triggerClickAnalytics}
type="flex"
gutter={16}
key={res._id}
style={{ margin: "20px auto", borderBottom: "1px solid #ededed" }}
>
<Col style={{ width: "360px" }}>
<h3
style={{ fontWeight: "600" }}
dangerouslySetInnerHTML={{
__html: title || "Choose a valid Title Field"
}}
/>
</Col>
<div style={{ padding: "20px" }} />
<Col>
<p
style={{ fontSize: "1em", width: "300px" }}
dangerouslySetInnerHTML={{
__html: system || "Choose a valid Description Field"
}}
/>
</Col>
<div style={{ padding: "10px" }} />
<Col>
<p
style={{ fontSize: "1em" }}
dangerouslySetInnerHTML={{
__html: unit || "-"
}}
/>
</Col>
<div style={{ padding: "10px" }} />
<Col style={{ minWidth: "120px" }}>
<p
style={{ fontSize: "1em", width: "300px"}}
dangerouslySetInnerHTML={{
__html: proposed || "Choose a valid Description Field"
}}
/>
</Col>
<div style={{ padding: "10px" }} />
<Col>
<p
style={{ fontSize: "1em"}}
dangerouslySetInnerHTML={{
__html: Math.round(score) || "Choose a valid Description Field"
}}
/>
</Col>
<Col>
<Button
shape="circle"
icon={<CheckOutlined />}
style={{ marginRight: "5px" }}
onClick={()=> {addFunc(resultdata)}}
/>
</Col>
</Row>
);
}
Basically, my ReactiveList component is what shows the results. This calls the RenderItem function, which is what displays the data on the screen. In my function, I have a list called resultdata, which contains all the data I need when each result is clicked on. This works, but I need it to display on the screen.
I can't use state, because I have a function. And I can't use hooks because it isn't the main function. Am I doing something wrong? Is there any other alternative to this?
Even if you can't provide a complete answer, I would appreciate any tips on which direction I should look towards.
state is async so it wont update like this:
function addFunc(resultdata){
console.log(resultdata)
selectedData = [...selectedData, resultdata]
console.log(selectedData)
};
and you are using a class so you can't useHooks but setState takes a callback as second argument
function addFunc(resultdata){
console.log(resultdata)
this.setState({selectedData: [...selectedData, resultdata]}, () => console.log(selectedData))
};
so if you continue using a Class approach this will allow you to use setState and utilize the callback in it
there is a callback available too in hooks but it doesn't work quite the same
Place addFunc within the parent component and make your RenderItem function a React Functional component by exporting it. Then provide the addFunc as a function prop from parent component to RenderItem component. That way you can call the function within onClick event. Any of the parent states can be updated from the addFunc. You can supply necessary arguments to the function call as well.

ReactJS In a user profile display only fields that have a value

Objective
Displaying only the fields that are filled in.
Background
In my application people will first fill out the application which has fields like "early reg fee, early reg date, regular reg fee, regular reg date" and so after they fill out all the information and click "view profile" they will see all the fields whether it's filled out or not.
If the value of one of the fields is null or undefined then it would not show up in the profile.
I was trying to do this and I started of by creating a state in the constructor "this.state {value: ''}"
class CompetitionProfileView extends React.Component {
constructor(props) {
super(props);
this.state {value: ''}
this.getContactCard = this.getContactCard.bind(this);
}
getCompetitionValue(path) {
const value = _.get(this.props.competition, path);
return value ? value : '';
}
getCompetitionDateValue(path) {
const value = _.get(this.props.competition, path);
return value ? value.toDateString() : '';
}
getCompetitionTimeValue(path) {
const value = _.get(this.props.competition, path);
return value ? `${
value.getHours() - 12
}:${value.getMinutes()}` : '';
}
getContactCard(num) {
return
this.getCompetitionValue(`Information.contactFirstName${num}`) ?
<Card key={num} style={{backgroundColor: '#f9f9f9', width: '32%'}} zDepth={2}>
<CardTitle title={`${this.getCompetitionValue(`Information.contactFirstName${num}`)} ${this.getCompetitionValue(`Information.contactFirstName${num}`)}`} subtitle={`${this.getCompetitionValue('Information.contactPosition1')}`} />
<Divider/>
<CardText>
<p style={{display: 'flex', justifyContent: 'center'}}><Phone/>{`${this.getCompetitionValue(`Information.contactFirstName${num}`)}`}</p>
<p style={{display: 'flex', justifyContent: 'center'}}><Email/>{`${this.getCompetitionValue(`Information.contactFirstName${num}`)}`}</p>
</CardText>
</Card>
:
'';
}
render(actions) {
return (
<div>
<div className="profileheader" style={{display: 'flex', flexDirection: 'column'}}>
<Paper className='banner-image' style={{backgroundImage: `url(${this.getCompetitionValue('Resources.boardPicture.url')})`,backgroundSize: 'cover',width: '100%', height: '200px', backgroundPositionY: '20%'}} zDepth={3}>
{/* <br style={{lineHeight: '15'}}/> */}
</Paper>
<Paper className='text-main' style={{textAlign: 'center'}}>
<label>{this.getCompetitionValue('Information.name')}</label>
</Paper>
<Paper className='logo-image' style={{backgroundImage: `url(${this.getCompetitionValue('Resources.competitionLogo.url')})`, backgroundSize: 'cover', width: '100px', height: '100px', marginTop: '-110px', marginLeft: '3%', paddingbottom: '20px'}} zDepth={3}/>
</div>
<hr/>
<div style={{display: 'flex', justifyContent: 'space-between'}}>
<Card style={{backgroundColor: '#f9f9f9', width: '49%'}} zDepth={2}>
<RaisedButton style={{display: 'flex', justifyContent: 'center'}} primary={true} label="Application Packet" onClick={() => window.open(this.getCompetitionValue('Resources.applicationPacket.url'), '_blank')}/>
</Card>
<Card style={{backgroundColor: '#f9f9f9', width: '49%'}} zDepth={2}>
<RaisedButton style={{display: 'flex', justifyContent: 'center'}} primary={true} label="Audition Video Info" onClick={() => window.open(this.getCompetitionValue('Resources.auditionVideoInfo.url'), '_blank')}/>
</Card>
</div>
<br/>
<div className='mainbody' style={{display: 'flex', flexDirection: 'row', justifyContent: 'space-between'}}>
<br/>
<div className='rightbody' style={{display: 'flex', flexDirection: 'column', width: '60%', flexWrap: 'wrap'}}>
<Card style={{backgroundColor: '#F0EFEF'}} zDepth={2}>
<CardHeader title="About Us" />
<Divider/>
<CardText>{`${this.getCompetitionValue('Information.compBlurb')}`}</CardText>
</Card>
<br/>
<Card style={{backgroundColor: '#F0EFEF'}} zDepth={2}>
<CardHeader title="Application Information" />
<Divider/>
<CardText>
<p><b>Early Reg:</b>{` ${this.getCompetitionDateValue('Information.dueDateEarly')}`}</p>
<p><b>Early Reg Fee:</b>{` ${this.getCompetitionValue('Information.earlyDues')}`}</p>
<p><b>Regular Reg:</b>{` ${this.getCompetitionDateValue('Information.dueDateRegular')}`}</p>
<p><b>Regular Reg Fee:</b>{` ${this.getCompetitionValue('Information.regularDues')}`}</p>
<p><b>Late Reg:</b>{` ${this.getCompetitionDateValue('Information.dueDateLate')}`}</p>
<p><b>Late Reg Fee:</b>{` ${this.getCompetitionValue('Information.lateDues')}`}</p>
<p><b>Applications Due At:</b>{` ${this.getCompetitionTimeValue('Information.dueTime')}`}</p>
<p><b>Time Zone:</b>{` ${this.getCompetitionValue('Information.timeZone')}`}</p>
<p><b>Penalties:</b>{` ${this.getCompetitionValue('Information.extraFees')}`}</p>
<p><b>Hear Back Date:</b>{` ${this.getCompetitionDateValue('Information.hearbackDate')}`}</p>
<p><b>Payment Method:</b>{` ${this.getCompetitionValue('Information.paymentMethods')}`}</p>
<br/>
</CardText>
</Card>
</div>
</div>
<br/>
<div className="contactinfo" style={{display: 'flex', justifyContent: 'space-around'}}>
{[1,2,3].map((num) => this.getContactCard(num))}
</div>
<br/>
{this.props.competition.Board.length > 0 &&
<Card style={{backgroundColor: '#F0EFEF'}} zDepth={2}>
<Table >
<TableHeader adjustForCheckbox={false} displaySelectAll={false}>
<TableRow>
{ Object.keys(this.props.competition.Board[0]).map((key) => <TableHeaderColumn key={key}>{key}</TableHeaderColumn>) }
</TableRow>
</TableHeader>
<TableBody displayRowCheckbox={false}>
{this.props.competition.Board.map((row, i) => (
<TableRow key={i}>
{ Object.keys(row).map((column) => <TableRowColumn key={column}>{row[column].name ? row[column].name : row[column]}</TableRowColumn>) }
</TableRow>
))
}
</TableBody>
</Table>
</Card>
}
</div>
);
}
}
const mapStateToProps = (state) => {
return {
messages: state.messages
};
};
export default connect(mapStateToProps)(CompetitionProfileView);
You can use if statements in your render() function, like so:
render() {
if (this.props.thing1) {
return <h1>Thing 1</h1>
} else {
return (
<div className="warning">
<h2>Thing 2</h2>
</div>
)
}
}
You can even use functions in the render() function like this:
renderASmallPart() {
if (this.props.thing1) {
return <h1>Thing 1</h1>
} else {
return (
<div className="warning">
<h2>Thing 2</h2>
</div>
)
}
}
render() {
return (
<div>
<h1>My App</h1>
<h2>Here's a thing:</h2>
{this.renderASmallPart()}
</div>
)
}
You can use this to break up your large render() function into smaller functions that check what the value of their field is and only render something when the field has a non-empty value
You need to look into Conditional Rendering and only render that element when there is a value.
https://facebook.github.io/react/docs/conditional-rendering.html
https://atticuswhite.com/blog/render-if-conditionally-render-react-components/
http://devnacho.com/2016/02/15/different-ways-to-add-if-else-statements-in-JSX/
https://kylewbanks.com/blog/how-to-conditionally-render-a-component-in-react-native

Categories