React Formik file upload with laravel back-end - javascript

I'am using Formik for my forms in React. Everything is okay but for the file input.
The user must be able to upload a CV. The {values.cv} in Formik does indicate that there is a value in the input. However when I send it to my Laravel back-end, I get an empty array.
I want to be able to store the file in my database.
Any help would be appreciated.
The Formik file input:
<label className="btn btn-info" htmlFor="cv">
<input id="cv" name="cv" style={{display: 'none'}} type="file" onChange={(event) => {
setFieldValue("cv", event.currentTarget.files[0]);
}} />
</label>
The cv input default value is : ' '
This is what is in the {values.cv}
Here is the console.log of it
In my Laravel back-end I return the $request and React is logging it.
This is what I see then.
cv : []
Here is a picture of my console

As per this post.
<input id="file" name="file" type="file" onChange={(event) => {
setFieldValue("file", event.currentTarget.files[0]);
}} />
You can then access all the stuff...
JSON.stringify({
fileName: values.file.name,
type: values.file.type,
size: `${values.file.size} bytes`
}, null, 2);

Formik doesn't handle file upload, but there's a hack around it provided here https://github.com/jaredpalmer/formik/issues/45
import * as React from 'react';
import { AxiosRequestConfig } from 'axios';
import Image from 'components/Image';
import { Progress } from 'components/Progress';
import ToasterInstance from '../Toast/ToasterInstance';
import { axios } from 'api/axios.config';
import { toApiError } from 'utils/api';
export interface MediaUploadProps {
id: string;
slug: string;
value: string;
onChange: (field: string, mediaId: string) => void;
}
export interface MediaUploadState {
progress: number;
file?: File;
error?: string;
}
export class MediaUpload extends React.Component<
MediaUploadProps,
MediaUploadState
> {
state: MediaUploadState = { progress: -1 };
handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
if (!e.target.files) {
return;
}
let file = e.target.files[0];
this.setState({ file: file });
let data = new FormData();
data.append('file', file);
let config: AxiosRequestConfig = {
onUploadProgress: (p: any) => {
this.setState({ progress: Math.round(p.loaded * 100 / p.total) });
},
};
this.setState({ error: undefined, progress: 0 });
axios.post('/v1/media?slug=' + this.props.slug, data, config).then(
res => {
this.setState({ error: undefined, progress: -1 });
this.props.onChange(this.props.id, res.data.path);
},
err => {
const message = toApiError(err);
this.setState({ error: message, progress: -1 });
ToasterInstance.show({
message,
iconName: 'danger',
intent: 'danger',
});
}
);
}
handleRemoveImage = () => {
this.props.onChange(this.props.id, '');
}
render() {
return (
<div>
<div>
{this.props.value !== '' &&
this.state.progress === -1 &&
<Image path={this.props.value} size="lg" />}
<div style={{ maxWidth: 144 }}>
{this.state.progress > -1 &&
<Progress percentage={this.state.progress} />}
</div>
{this.props.value &&
<a
style={{ marginTop: -40 }}
className="button button--negative button--small button--secondary"
role="button"
onClick={this.handleRemoveImage}
>
Remove
</a>}
</div>
<div style={{ marginTop: 10 }}>
<label className="button button--purple button--secondary">
Upload new picture
<input
className="visually-hidden"
type="file"
onChange={this.handleFileChange}
/>
</label>
</div>
</div>
);
}
}

Related

After Delete Mutation not Refetching Query (Apollo Graphql & Nextjs)

I recently switched my reactjs code to nextjs code, and I've observed that while I'm in reactjs code, When I delete data or perform a delete action, it appears like the queries are re-fetched and I am given the most recent or updated data in the datatable, but when I attempt it on Nextjs, it does not work. Is there a way to fix this?
Keep note I am using client side for this action.
Code
Form.js
export default function MainCategoryForm() {
const [name, setName] = useState("");
const [file, setFile] = useState();
const [status, setStatus] = useState("");
const [createMainCategory, { loading }] = useMutation(
CREATE_MAINCATEGORY_MUTATION
);
async function onSubmit() {
const res = await createMainCategory({
variables: {
name,
slug: name.toLowerCase(),
file,
status,
},
update: (cache, { data: { createMainCategory } }) => {
const { mainCategories } = cache.readQuery({
query: FETCH_MAINCATEGORIES_QUERY,
});
cache.writeQuery({
query: FETCH_MAINCATEGORIES_QUERY,
data: { mainCategories: mainCategories.concat([createMainCategory]) },
});
},
refetchQueries: [{ query: FETCH_MAINCATEGORIES_QUERY }],
});
if (res) {
toast.success(`Main Category Created`, { autoClose: 2000 });
setName("");
setStatus("");
setFile("");
}
}
console.log(file);
return (
<>
<Form onSubmit={onSubmit} className={loading ? "loading" : ""}>
<h2>Create a Main Category:</h2>
<Form.Field>
<input
name="file"
type="file"
onChange={(event) => {
setFile(event.target.files[0]);
}}
/>
<Form.Input
placeholder="Please Enter Name"
name="name"
label="Name: "
onChange={(event) => {
setName(event.target.value);
}}
value={name}
/>
<label>Status: </label>
<select
name="category"
className="form-control"
onChange={(event) => {
setStatus(event.target.value);
}}
value={status}
>
<option active="true" hidden>
Please Enter Status
</option>
<option value="Activated">Activated</option>
</select>
<br />
<Button type="submit" color="teal">
Submit
</Button>
</Form.Field>
</Form>
</>
);
}
As shown above this code I have this refetchQueries: [{ query: FETCH_MAINCATEGORIES_QUERY }], in which after the add mutation or mutation it will refetch the query needed for the recent data to show in my datatable, I tried also putting that in the DeleteButton Component but it doesn't work.
Table
export default function MainCategoryTable({
mainCategory: { id, name, slug, status, url, createdAt },
}) {
return (
<>
<tr>
<td>{id}</td>
<td>
<img src={url} width={300} />
</td>
<td>{name}</td>
<td>{slug}</td>
<td>{status}</td>
<td>{dayjs(createdAt).format("h:mm:ss a")}</td>
<td>
<DeleteButton name={name} mainCategoryId={id} />
<Button>
<Link href={`/mainCategories/${id}`}>
<Icon name="edit" style={{ margin: 0 }} />
</Link>
</Button>
</td>
</tr>
</>
);
}
DeleteButton Component
export default function DeleteButton({ mainCategoryId, callback }) {
const [confirmOpen, setConfirmOpen] = useState(false);
const mutation = DELETE_MAINCATEGORY_MUTATION;
const [deleteMainCategoryOrMutation] = useMutation(mutation, {
update(proxy) {
setConfirmOpen(false);
if (mainCategoryId) {
const data = proxy.readQuery({
query: FETCH_MAINCATEGORIES_QUERY,
});
data.getMainCategories = data.getMainCategories.filter(
(ap) => ap.id !== mainCategoryId
);
toast.error(`Main Category Deleted`, { autoClose: 2000 });
proxy.writeQuery({ query: FETCH_MAINCATEGORIES_QUERY, data });
}
if (callback) callback();
},
variables: {
mainCategoryId,
},
});
return (
<>
<MyPopup content={"Delete Main Category"}>
<Button
as="div"
color="red"
floated="right"
onClick={() => setConfirmOpen(true)}
>
<Icon name="trash" style={{ margin: 0 }} />
</Button>
</MyPopup>
<Confirm
open={confirmOpen}
onCancel={() => setConfirmOpen(false)}
onConfirm={deleteMainCategoryOrMutation}
/>
</>
);
}
If you need any more code, such as my backend or any files to figure out what's wrong, I'll always amend my article. If you need any clarification or don't understand what I mean, please leave a comment down below.
You didn't set the refetchQueries in the DELETE_MAINCATEGORY_MUTATION mutation, instead you used the update option and read the query from the cache but you mutated the data, which is not the right way to do it, instead you should return a new array as follows:
const [deleteMainCategoryOrMutation] = useMutation(mutation, {
update(proxy) {
setConfirmOpen(false);
if (mainCategoryId) {
const previousData = proxy.readQuery({ query: FETCH_MAINCATEGORIES_QUERY });
const getMainCategories = previousData.getMainCategories.filter(
(ap) => ap.id !== mainCategoryId
);
const data = {
getMainCategories,
};
toast.error(`Main Category Deleted`, { autoClose: 2000 });
proxy.writeQuery({ query: FETCH_MAINCATEGORIES_QUERY, data });
}
if (callback) callback();
},
variables: {
mainCategoryId,
},
});

Test for null after hitting submit button using ternary or conditional operator

What I am trying to achieve:
I am trying to pass the value of fileId as N if sessionStorage.getItem('uploadedFiles') is null. However, if the value exists, I want to pass the existing value from the session storage.
Scenario 1:
User may submit a form without uploading the file. In this case, the value of sessionStorage.getItem('uploadedFiles') is going to be null.
Scenario 2 :
User uploads a file using the Attach Files button. So inside fileUpload function, I am storing the value of fileId in session storage using the following code:
growlComp.show({severity: 'success', summary: 'File Upload successful', detail: 'File Upload was successful'})
sessionStorage.setItem('uploadedFiles', JSON.stringify(fileArray))
Problem:
Inside mapPropsToValues: props => {, as shown in the code below,I have tried to put a check using var fileIdValue = sessionStorage.getItem('uploadedFiles') ;
but this always prints null when a submit button is clicked, regardless of someone uploading the file or not.
How can I test for the null inside this line of code for the fileId variable and if it is null, I want to send fileId: ['N'], and if it is not null, then I want to send the value from the session storage?
I was thinking of using ternary expression but that doesn't fit with if statement.
return {
createDate: props.testRequest && props.testRequest.createDate || '',
startDate: props.testRequest && props.testRequest.startDate || '',
completeDate: props.testRequest && props.testRequest.completeDate || '',
edwEmployeeId: props.testRequest && props.testRequest.employeeId || '',
fileId: [sessionStorage.getItem('uploadedFiles')],
}
Here is my code (many things are removed for brevity purpose)
import React from 'react';
import {Field, Form, useField, withFormik} from 'formik';
import {Button, InputLabel,Menu,MenuItem, Select, TextField, TextareaAutosize} from '#material-ui/core'
import * as Yup from 'yup'
import {AutoCompanys} from './forms/AutoCompanys';
//more imports here
const CompanyRequestFormAbc = (props) => {
const {values, setFieldValue, touched, errors, isSubmitting, handleReset, handleChange} = props;
const fileUpload = (e) => {
console.log('fileupload triggered....' + e.files)
const growlComp = growl.current
let formData = new FormData();
e.files.forEach((file, i) => formData.append(`files`, file))
axios.post('abc/userFileUpload?//some parameters, formData,{
headers: {
"Content-Type": "multipart/form-data"
}
}).then((response) => {
var filedata = response.data;
filedata = filedata.filter(v=>v!='');
var fileArray = [];
filedata.forEach(element => {
if(element.indexOf(",")){
var splitString = element.split(",");
fileArray.push(splitString[0]);
}
});
growlComp.show({severity: 'success', summary: 'File Upload successful', detail: 'File Upload was successful'})
sessionStorage.setItem('uploadedFiles', JSON.stringify(fileArray))
}).catch((response) => {
growlComp.show({severity: 'error', summary: 'File Upload unsuccessful', detail: 'File Upload was unsuccessful'})
console.log('Could not upload files.....')
})
}
return (
<div>
<div id="formDiv">
<Form className="form-column-3">
<div className="form-field">
<FileUpload
name="files"
mode='advanced'
uploadHandler={fileUpload}
customUpload={true}
chooseLabel="Attach Files"
multiple={false}/>
</div>
</div>
<div className="btn-group-right">
<Button size="large" variant="contained" color="primary"
type="submit">Submit</Button>
<Button size="large" variant="contained" color="primary" onClick={handleReset}
style={{marginLeft: '5px'}} type="button">Reset</Button>
<Button size="large" variant="contained" color="primary" onClick={props.onCancel}
style={{marginLeft: '5px'}} type="button">Cancel</Button>
</div>
</Form>
</div>
</div>
)
};
export const CompanyRequestEnhancedFormAbc = withFormik({
mapPropsToValues: props => {
//Test the value of fileId. If the value is null, then we need to send 'N' as an asnwer
var fileIdValue = sessionStorage.getItem('uploadedFiles') ;
console.log("****************************************************************")
console.log("fileId value from session storage")
console.log(fileIdValue);
if(fileIdValue === null){
console.log("fileId Value is NULL after null check inside const CompanyRequestEnhancedFormAbc");
}else {
console.log ("fileId value is not null inside const CompanyRequestEnhancedFormAbc")
}
return {
createDate: props.testRequest && props.testRequest.createDate || '',
startDate: props.testRequest && props.testRequest.startDate || '',
completeDate: props.testRequest && props.testRequest.completeDate || '',
edwEmployeeId: props.testRequest && props.testRequest.employeeId || '',
fileId: [sessionStorage.getItem('uploadedFiles')],
}
},
validationSchema:validationSchema,
handleSubmit(values, {props, resetForm, setErrors, setSubmitting}) {
// Do something
},
setFieldValue(field, value, shouldVal) {
console.log('In setFieldValue')
},
displayName: 'Company Request Form',
})(CompanyRequestFormAbc)

how to fix Error componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops

I use react js to create a staycation website, when I want to display the InputNumber and InputDate components I experience an error like the title above, in the componentDidUpdate section, I have tried tweaking the code but it hasn't worked, but when I omit the componentDidUpdate part, the inputdate and inputnumber components run.
this is the input component code Number I have tried the input component works well,:
import React from "react";
import propTypes from "prop-types";
import "./index.scss";
export default function Number(props) {
const {
value,
placeholder,
name,
min,
max,
prefix,
suffix,
isSuffixPlural,
} = props;
const onChange = (e) => {
let value = String(e.target.value);
if (+value <= max && +value >= min) {
props.onChange({
target: {
name: name,
value: +value,
},
});
}
};
const minus = () => {
value > min &&
onChange({
target: {
name: name,
value: +value - 1,
},
});
};
const plus = () => {
value < max &&
onChange({
target: {
name: name,
value: +value + 1,
},
});
};
return (
<div className={["input-number mb-3", props.outerClassName].join(" ")}>
<div className="input-group">
<div className="input-group-prepend">
<span className="input-group-text minus" onClick={minus}>
-
</span>
</div>
<input
min={min}
max={max}
name={name}
pattern="[0-9]*"
className="form-control"
placeholder={placeholder ? placeholder : "0"}
value={`${prefix}${value}${suffix}${
isSuffixPlural && value > 1 ? "s" : ""
}`}
onChange={onChange}
/>
<div className="input-group-append">
<span className="input-group-text plus" onClick={plus}>
+
</span>
</div>
</div>
</div>
);
}
Number.defaultProps = {
min: 1,
max: 1,
prefix: "",
suffix: "",
};
Number.propTypes = {
value: propTypes.oneOfType([propTypes.string, propTypes.number]),
onChange: propTypes.func,
placeholder: propTypes.string,
isSuffixPlural: propTypes.bool,
outerClassName: propTypes.string,
};
and this is my input date component code I have tried the input component works well, :
import React, { useState, useRef, useEffect } from "react";
import propTypes from "prop-types";
import { DateRange } from "react-date-range";
import "./index.scss";
import "react-date-range/dist/styles.css"; // main css file
import "react-date-range/dist/theme/default.css"; // theme css file
import formatDate from "utils/formatDate";
import iconCalendar from "assets/images/icon/icon-calendar.svg";
export default function Date(props) {
const { value, placeholder, name } = props;
const [isShowed, setIsShowed] = useState(false);
const datePickerChange = (value) => {
const target = {
target: {
value: value.selection,
name: name,
},
};
props.onChange(target);
};
useEffect(() => {
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
});
const refDate = useRef(null);
const handleClickOutside = (event) => {
if (refDate && !refDate.current.contains(event.target)) {
setIsShowed(false);
}
};
const check = (focus) => {
focus.indexOf(1) < 0 && setIsShowed(false);
};
const displayDate = `${value.startDate ? formatDate(value.startDate) : ""}${
value.endDate ? " - " + formatDate(value.endDate) : ""
}`;
return (
<div
ref={refDate}
className={["input-date mb-3", props.outerClassName].join(" ")}
>
<div className="input-group">
<div className="input-group-prepend bg-gray-900">
<span className="input-group-text">
<img src={iconCalendar} alt="icon calendar" />
</span>
</div>
<input
readOnly
type="text"
className="form-control"
value={displayDate}
placeholder={placeholder}
onClick={() => setIsShowed(!isShowed)}
/>
{isShowed && (
<div className="date-range-wrapper">
<DateRange
editableDateInputs={true}
onChange={datePickerChange}
moveRangeOnFirstSelection={false}
onRangeFocusChange={check}
ranges={[value]}
/>
</div>
)}
</div>
</div>
);
}
Date.propTypes = {
value: propTypes.object,
onChange: propTypes.func,
placeholder: propTypes.string,
outerClassName: propTypes.string,
};
I have tried the inpudate component to run well, as well as the input number, but if I combine these components I have an error did i miss something, and I tried to combine these components on the bookingform page but when I tried on the browser I experienced the above error.
My code is in the Booking Form:
import React, { Component } from "react";
import propTypes from "prop-types";
import Button from "elements/Button";
import { InputNumber, InputDate } from "elements/Form";
export default class BookingForm extends Component {
constructor(props) {
super(props);
this.state = {
data: {
duration: 1,
date: {
startDate: new Date(),
endDate: new Date(),
key: "selection",
},
},
};
}
updateData = (e) => {
this.setState({
...this.state,
data: {
...this.state.data,
[e.target.name]: e.target.value,
},
});
};
componentDidUpdate(prevProps, prevState) {
const { data } = this.state;
if (prevState.data.date !== data.date) {
const startDate = new Date(data.date.startDate);
const endDate = new Date(data.date.endDate);
const countDuration = new Date(endDate - startDate).getDate();
this.setState({
data: {
...this.state.data,
duration: countDuration,
},
});
}
if (prevState.data.duration !== data.duration) {
const startDate = new Date(data.date.startDate);
const endDate = new Date(
startDate.setDate(startDate.getDate() + +data.duration - 1)
);
this.setState({
...this.state,
data: {
...this.state.data,
date: {
...this.state.data.date,
endDate: endDate,
},
},
});
}
}
startBooking = () => {
const { data } = this.state;
this.props.startBooking({
_id: this.props.itemDetails._id,
duration: data.duration,
date: {
startDate: data.date.startDate,
endDate: data.date.endDate,
},
});
this.props.history.push("/checkout");
};
render() {
const { data } = this.state;
const { itemDetails } = this.props;
console.log(this.state);
return (
<div className="card bordered" style={{ padding: "60px 80px" }}>
<h4 className="mb-3">Start Booking</h4>
<h5 className="h2 text-teal mb-4">
${itemDetails.price}{" "}
<span className="text-gray-500 font-weight-light">
per {itemDetails.unit}
</span>
</h5>
<label htmlFor="duration">How long you will stay?</label>
<InputNumber
max={30}
suffix={" night"}
isSuffixPlural
onChange={this.updateData}
name="duration"
value={data.duration}
/>
<label htmlFor="date">Pick a date</label>
<InputDate onChange={this.updateData} name="date" value={data.date} />
<h6
className="text-gray-500 font-weight-light"
style={{ marginBottom: 40 }}
>
You will pay{" "}
<span className="text-gray-900">
${itemDetails.price * data.duration} USD
</span>{" "}
per{" "}
<span className="text-gray-900">
{data.duration} {itemDetails.unit}
</span>
</h6>
<Button
className="btn"
hasShadow
isPrimary
isBlock
onClick={this.startBooking}
>
Continue to Book
</Button>
</div>
);
}
}
BookingForm.propTypes = {
itemDetails: propTypes.object,
startBooking: propTypes.func,
};
I encountered this error and tried to fix it, but couldn't find a solution to the problem
I use react js to create a staycation website, when I want to display the InputNumber and InputDate components I experience an error like the title above, in the componentDidUpdate section, I have tried tweaking the code but it hasn't worked, but when I omit the componentDidUpdate part, the inputdate and inputnumber components run.
I encountered this error and tried to fix it, but couldn't find a solution to the problem
I use react js to create a staycation website, when I want to display the InputNumber and InputDate components I experience an error like the title above, in the componentDidUpdate section, I have tried tweaking the code but it hasn't worked, but when I omit the componentDidUpdate part, the inputdate and inputnumber components run.
I encountered this error and tried to fix it, but couldn't find a solution to the problem
I use react js to create a staycation website, when I want to display the InputNumber and InputDate components I experience an error like the title above, in the componentDidUpdate section, I have tried tweaking the code but it hasn't worked, but when I omit the componentDidUpdate part, the inputdate and inputnumber components run.

REACT: What I should write in propTypes when in form I use input type="file'?

I make form using Formik in my app. When I send form to my local server I create image with title. Attach images I should using input type="file".But I have very little experience using the formik.
What I should write in propTypes when in form I use input type="file' in file InputImage.js?
And How to add input type="file" in file AddImage.js in mark place?
Now I want to create input which attach image component InputImage.js similar to InputTitle.js.
I comment line where I dont know what I should write.
AddImage.js:
const AddImage = (props) => {
const {handleSubmit, values, handleChange} = useFormik({
initialValues: {
title: '',
image: '' // Did I write correctly here?
},
validateOnchange: false,
onSubmit: async (formValues) => {
const response = await api(`${imageRoutePath}`, {
method:'POST',
body: JSON.stringify(formValues),
});},
});
return (
<div>
<form onSubmit={handleSubmit}>
<InputTitle
label="title"
id="title"
inputProps={{
name:'title',
value: values.title,
onChange: handleChange,
}}
/>
<InputImage
label="image"
id="image"
inputProps={{
name:'image',
// WHAT I SHOULD WRITE THERE?
onChange: handleChange,
}}
/>
<button type="submit" disabled={isSubmitting}>Add</button>
</form>
</div>
);
};
export default AddImage;
InputImage.js:
const InputImage = ({
label, inputProps, error, id,
}) => (
<div className="formInputCategory">
<label htmlFor={id} className="formInputLabelCategory">
{label}
</label>
<input {...inputProps} id={id} />
{error && <span className="formInputErrorCategory">{error}</span>}
</div>
);
InputImage.propTypes = {
label: PropTypes.string.isRequired,
// WHAT I SHOULD WRITE THERE?
error: PropTypes.string,
id: PropTypes.string.isRequired,
};
InputImage.defaultProps = {
error: '',
}
---------------------------------------------------------------------------------------
example how I write InputTitle.js:
const InputTitle = ({
label, inputProps, error, id,
}) => (
<div className="formInputCategory">
<label htmlFor={id} className="formInputLabelCategory">
{label}
</label>
<input {...inputProps} id={id} />
{error && <span className="formInputErrorCategory">{error}</span>}
</div>
);
InputTitle.propTypes = {
label: PropTypes.string.isRequired,
inputProps: PropTypes.instanceOf(Object).isRequired,
error: PropTypes.string,
id: PropTypes.string.isRequired,
};
InputTitle.defaultProps = {
error: '',
}
Formik doesnot support fileupload by default, But you can try the following
<input id="file" name="file" type="file" onChange={(event) => {
setFieldValue("file", event.currentTarget.files[0]);
}} />
Here "file" represents the key that you are using for holding the file
setFieldValue is obtained from <Formik />
reference : formik setFieldValue prop
your code will look like :
const AddImage = (props) => {
const {handleSubmit, values, handleChange, setFieldValue } = useFormik({
initialValues: {
title: '',
image: '' // Did I write correctly here?
},
validateOnchange: false,
onSubmit: async (formValues) => {
const response = await api(`${imageRoutePath}`, {
method:'POST',
body: JSON.stringify(formValues),
});},
});
return (
<div>
<form onSubmit={handleSubmit}>
<InputTitle
label="title"
id="title"
inputProps={{
name:'title',
value: values.title,
onChange: handleChange,
}}
/>
<InputImage
label="image"
id="image"
inputProps={{
name:'file',
id="file",
// WHAT I SHOULD WRITE THERE?
type="file",
onChange={(event) => {
setFieldValue("file", event.currentTarget.files[0]);
}},
}}
/>
<button type="submit" disabled={isSubmitting}>Add</button>
</form>
</div>
);
};
export default AddImage;

How to add if-else statement within onClick event based on radio buttons

I currently have a page that loads in 2 seperate lists of data as cards from two seperate URLs I have that are as follows:
http://localhost:3000/videos
http://localhost:3000/manuals
So I have a div that loads up two seperate list components and displays them together. I also have a "Create Card" button that opens a modal, and once the information needed is filled in and the submit button is clicked, the onClick of the button loads up the "CreateCard" function.
Originially, I had a working page that would create cards successfully but it would only submit it to /videos. I have now created 2 seperate functions, one that creates /videos and on that creates /modules. Furthermore, I have added radio buttons that allows the user to decide on whether they are creating a /module or /video card. The code for the creating form is as follows:
<Popup
trigger={<button className="btn blue-outline"> Create a new card</button>}
modal
position="right center">
<div>
<div>
<label>Title:</label>
<input
style={{ width: "100%" }}
className="input"
name="createCardTitle"
onChange={(e) => {
this.setState({ title: e.target.value });
}}
value={this.state.title}></input>
</div>
<div>
<label>URL:</label>
<input
style={{ width: "100%" }}
className="input"
name="createCardURL"
onChange={(e) => {
this.setState({ url: e.target.value });
}}></input>
</div>
<div>
<label>Thumbnail URL:</label>
<input
style={{ width: "100%" }}
className="input"
name="createCardThumbnail"
onChange={(e) => {
this.setState({ thumbnail: e.target.value });
}}
value={this.state.thumbnail}></input>
</div>
<label className="radio">
<input
id="videoCardRadio"
type="radio"
name="radio_group_1"
value="video"
checked={this.state.whichRadioSelected === "video"}
onChange={() => this.setState({ whichRadioSelected: "video" })}
/>
<span>Video Card</span>
</label>
<label className="radio">
<input
id="manualCardRadio"
type="radio"
name="radio_group_1"
value="manual"
checked={this.state.whichRadioSelected === "manual"}
onChange={() => this.setState({ whichRadioSelected: "manual" })}
/>
<span>Manual Card</span>
</label>
<br></br>
<button
style={{
float: "left"
}}
onClick={() => this.createManualProduct(this.state.title, this.state.url, this.state.thumbnail)}
className="btn blue-outline"
id="confirmModalBtn">
Create
</button>
</div>
</Popup>
I am trying to figure out how I can implement an if-else statement that would be able to determine whether or not a "video" or "manual" radio button is selected, and depending on that, if "video" was selected, then the createVideoCard() function is run. And if "manual" is selected, then the createManualCard() function is run.
The code for the rest of the page is available below just incase it is needed for reference:
import React, { Component } from "react";
import HelpList from "../components/helpAdmin/help/HelpList";
import "../components/helpAdmin/help/HelpList";
import "../components/helpAdmin/help/ManualHelpList";
import "../components/helpAdmin/help/HelpCard";
import { Modal, Button, Tooltip, Icon, Tabs, Checkbox, Radio } from "components/ui";
import Popup from "reactjs-popup";
import ManualHelpList from "../components/helpAdmin/help/ManualHelpList";
interface Props {}
interface State {
url: string;
title: string;
adminhelpcard: SingleAdminHelpCard[];
error: null;
response: {};
thumbnail: string;
isEditProduct: boolean;
isAddProduct: boolean;
id: string;
whichRadioSelected: string;
}
interface SingleAdminHelpCard {
id: string;
url: string;
title: string;
thumbnail: string;
}
export class HelpAdminView extends Component<Props, State> {
state = {
title: "",
thumbnail: "",
id: "",
url: "http://localhost:3000/videos/",
adminhelpcard: [],
itemsCountPerPage: 1,
activePage: 1,
error: null,
response: {},
isEditProduct: true,
isAddProduct: true,
whichRadioSelected: ""
};
componentDidMount() {}
createVideoProduct(title: string, url: string, thumbnail: string) {
const { adminhelpcard } = this.state;
const apiUrl = `http://localhost:3000/videos/`;
const options = {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
title,
url,
thumbnail
})
};
fetch(apiUrl, options)
.then((res) => res.json())
.then(
(result) => {
this.setState({
response: result
});
},
(error) => {
this.setState({ error });
}
);
}
createManualProduct(title: string, url: string, thumbnail: string) {
const { adminhelpcard } = this.state;
const apiUrl = `http://localhost:3000/manuals/`;
const options = {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
title,
url,
thumbnail
})
};
fetch(apiUrl, options)
.then((res) => res.json())
.then(
(result) => {
this.setState({
response: result
});
},
(error) => {
this.setState({ error });
}
);
}
render() {
return (
<main>
<div className="box">
<Popup
trigger={<button className="btn blue-outline"> Create a new card</button>}
modal
position="right center">
<div>
<div>
<label>Title:</label>
<input
style={{ width: "100%" }}
className="input"
name="createCardTitle"
onChange={(e) => {
this.setState({ title: e.target.value });
}}
value={this.state.title}></input>
</div>
<div>
<label>URL:</label>
<input
style={{ width: "100%" }}
className="input"
name="createCardURL"
onChange={(e) => {
this.setState({ url: e.target.value });
}}></input>
</div>
<div>
<label>Thumbnail URL:</label>
<input
style={{ width: "100%" }}
className="input"
name="createCardThumbnail"
onChange={(e) => {
this.setState({ thumbnail: e.target.value });
}}
value={this.state.thumbnail}></input>
</div>
<label className="radio">
<input
id="videoCardRadio"
type="radio"
name="radio_group_1"
value="video"
checked={this.state.whichRadioSelected === "video"}
onChange={() => this.setState({ whichRadioSelected: "video" })}
/>
<span>Video Card</span>
</label>
<label className="radio">
<input
id="manualCardRadio"
type="radio"
name="radio_group_1"
value="manual"
checked={this.state.whichRadioSelected === "manual"}
onChange={() => this.setState({ whichRadioSelected: "manual" })}
/>
<span>Manual Card</span>
</label>
<br></br>
<button
style={{
float: "left"
}}
onClick={() => this.createManualProduct(this.state.title, this.state.url, this.state.thumbnail)}
className="btn blue-outline"
id="confirmModalBtn">
Create
</button>
</div>
</Popup>
<div className="listDisplay">
<HelpList />
<ManualHelpList />
</div>
</div>
</main>
);
}
}
export default HelpAdminView;
You can call createVideo if this.state.whichRadioSelected === "video" if not call createManuals like this
clickHandler = () => {
if(this.state.whichRadioSelected === "video") {
this.createVideo();
} else {
this.createManuals();
}
}
and in your button, pass this handler function to your onClick event like this
<Button onClick={() => {this.clickHandler();}}

Categories