why getting error while uploading image in react - file-upload

I created a form with name, order, image, status feild in my application. I used material design for form design and used react-material-file-upload for image upload.i got the values and viewed in console.After submitting the form it is not added in my web api,getting error in file.filename not defined in server.
Add.js
import FileUpload from "react-material-file-upload";
import TextField from '#mui/material/TextField';
import Grid from '#mui/material/Grid';
function Addcategory(props){
const [files, setFiles] = useState([]);
const handleSubmit =async (event) =>{
event.preventDefault();
const userid=localStorage.getItem("id");
const fileimg =files[0];
console.log(fileimg);
const userData = {
catname:event.target[0].value,
catorder:event.target[2].value,
image:fileimg,
enable:event.target[4].value,
status:1,
createdBy:userid
}
console.log(userData);
await CategoryDataService.create(userData)
.then(res => {
const data=res.data;
console.log(res);
toast.success("Category Added Successfully");
})
.catch((err) => {
// console.log("err",err.response);
toast.error("please try again!");
});
}
return(
<ThemeProvider theme={theme}>
<div style={{ margin:" 30px 130px 30px"}}>
<Box sx={{ border: '2px solid #15171c', borderRadius: '10px'}} >
<Grid container rowSpacing={1} columnSpacing={{ xs: 1, sm: 2, md: 3 }}>
<Grid item xs={12} style={{textAlign:"center"}}>
<h2 style={{textAlign:"center"}}>Category Add</h2>
<Box
component="form"
sx={{
'& .MuiTextField-root': { m: 1,},
}}
onSubmit={handleSubmit}
noValidate
autoComplete="off"
>
<div className="form-display">
<Grid >
<TextField
required
id="outlined-text"
label="Category Name"
name="catname"
autoFocus/>
<TextField
id="outlined-text"
label="Category Order"
name="catorder"
type="number"
/>
<TextField
id="outlined-select-currency"
select
label="Category Status"
name="enable"
helperText="Please select actegory status"
>
{catStatus.map((option) => (
<MenuItem key={option.value} value={option.value} >
{option.label}
</MenuItem>
))}
</TextField>
<Grid item xs={12} columnSpacing={{xs:1}}>
<Grid item xs={12}>
<FileUpload value={files} onChange={setFiles} />
</Grid>
</Grid>
<Stack direction="row" spacing={2} justifyContent="center"
style={{margin:"15px"}}>
<Button variant="outlined" type="submit">
Submit {props.children}
</Button >
<Button variant="outlined" onClick={back}>
Cancel
</Button>
</Stack>
</Grid>
</div>
</Box>
</Grid>
</Grid>
</Box>
</div>
</ThemeProvider>
);
}
server.js
const multer=require("multer");
const fileStorageEngine = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, "./uploads");
},
filename:(req, file, cb) =>{
cb(null, Date.now() + "-" + file.originalname);
}
});
const upload = multer({ storage: fileStorageEngine });
app.post('/addCategory', upload.single("image"), async(req,res)=>{
// let file = req.file;
const data={
category_order:req.body.catorder,
category_name:req.body.catname,
category_icon:req.file.filename,
category_enable_disable:req.body.enable,
status:req.body.status,
created_by:req.body.createdBy,
createdAt:Date.now()
}
await models.category.create(data).then(result=>{
res.status(201).json({
Code: "1",
Message: "Category created successfully",
Data: result
});
})
.catch(error=>{
res.status(500).json({
Code: "0",
Message: "Something went wrong,try again.",
Post: error
});
})
});
this api is working in postman but not working while submit the form

Related

Material UI TextField select not showing initial value on form edit

I have an edit form in a modal that lets you edit user info. Here is the relevant portion:
export const EditUserModal = (Props) => {
const [formValues, setFormValues] = useState(Props.userData);
const [reporterData, setReporterData] = React.useState<any[]>([]);
React.useEffect(() => {
let apiClient = new APIClient();
apiClient.getOwners().then((response) => {
setReporterData(response);
});
}, []);
const handleInputChange = (e) => {
const { name, value } = e.target;
setFormValues({
...formValues,
[name]: value,
});
};
return (
<>
<Modal
open={Props.show}
onClose={() => { Props.toggleModal(false)}}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
>
<Box
component="form"
autoComplete="off"
>
<Typography id="modal-modal-title" variant="h4" component="h4">
Edit User {Props.userData.name}
</Typography>
<div>
<TextField
required
id="outlined-select-basic"
select
name="reports_to"
label="Reports To"
value={formValues.reports_to}
onChange={handleInputChange}
>
{reporterData.map((option) => (
<MenuItem key={option.owner} value={option.owner}>
{option.owner}
</MenuItem>
))}
</TextField>
</div>
</Box>
</Modal>
</>
)
};
The TextField is supposed to show the initial value of {formValues.reports_to}, but it remains blank (the value is still correct) until you make a new selection. reporterData just returns a list of names(string).
I have tried adding it as a defaultValue, which did not work.

File upload using formik and express backend

I am trying to upload an image along with a title and some text for a post. I am using Formik form with an onSubmit in the client folder of the project :
const [charCount, setCharCount] = useState(0);
const [fileObject, setFileObject] = useState(null);
const initialValues = {
title: "",
postText: "",
file: null
};
const validationSchema = Yup.object({
title: Yup.string().required("Required"),
postText: Yup.string().required("Required"),
});
const onSubmitHandler = (values) => {
const formData = new FormData();
formData.append("title", values.title);
formData.append("postText", values.postText);
console.log(fileObject);
formData.append("file", document.getElementById("file").files[0]);
console.log(formData);
axios
.post(
"http://localhost:3001/posts/create",
formData,
{
headers: {
accessToken: localStorage.getItem("token"),
},
}
)
.then((response) => {
console.log(response.data);
});
};
return (
<>
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={onSubmitHandler}
>
<Form className="create-post-form">
<input type="file" name="file" id="file" onChange={(e) => {
setFileObject(e.target.files[0]);
}}/>
<Field id="input-create-post" name="title" placeholder="Post Title" />
<ErrorMessage name="title" component="span" className="error" />
<Field
id="input-create-post-text"
name="postText"
placeholder="What's the story?"
as="textarea"
onKeyUp={(e) => setCharCount(e.target.value.length)}
maxLength="250"
/>
<div className="char-count">
<span id={charCount===250 ? "char-count-max" : "char-count"}>{charCount}/250</span>
</div>
<ErrorMessage name="title" component="span" className="error" />
<Button type="submit" title="Post" onSubmit={onSubmitHandler} />
</Form>
</Formik>
</>
);
};
On the server side (server folder), in the Posts.js route where I am handling the request :
router.post("/create",validateToken, async(req,res)=>{
if(req.files === null){
return res.status(400).json({message: "No file uploaded"});
}
const file = req.files;
console.log(file);
res.json(req.body)
})
On submitting the form, an empty object {} is logged on the console. And the res.json(req.body) returns the title and postText successfully, but the file is {} (empty). How do I fix this? Please help!
I tried submitting the form with the above code and got this response:
result image
I need the file object to be the actual fileObject that I have as a state.

Why query not updated value but get initial value in Function with ExtReact

I have form fn
code here
#update code. I initialization
query = {
field: '',
email: '',
}
not initialization url
export function HomePage() {
const [query, setQuery] = useState({
field: '',
email: '',
});
const handleChaneValue = (value) => {
// not received data on change
console.log('query', query);
setQuery({
...query,
[value.sender.name]: value.newValue
})
}
console.log('query2', query);
query2 received data on change
console.log('query2', query);
#Update code: I add
return (
<div>
<Container
padding={10}
platformConfig={{
desktop: {
maxWidth: 400,
}
}}
>
<FormPanel
padding={10}
shadow
defaults={{
errorTarget: 'under'
}}
margin="0 0 20 0"
title="Using Validators"
>
<Textfield
required
label="Required Field"
requiredMessage="This field is required."
errorTarget="under"
name="field"
onChange={handleChaneValue}
/>
<EmailField
label="Email"
validators="email"
errorTarget="under"
name="email"
onChange={(e) => handleChaneValue(e)}
/>
<Urlfield
label="URL"
validators={{
type: 'url',
message: 'Website url example http://'
}}
errorTarget="under"
name="url"
onChange={handleChaneValue}
/>
<Container layout="center">
<Button
ui="confirm"
text="BTN submit"
handler={handleClick}
style={{border: '1px solid black' }}/>
</Container>
</FormPanel>
</Container>
</div>
)
}
export default HomePage;
When I change value in TextField. Query is
query2: {field: 'abc'}
But i change value in Email field. Query is not give old value "{filed: 'abc'}" throught I use ES6 three dot.
query2 : {email: 'xyz'}
and Query in funciton always initialization
query: {}
image change value
#Update image: when I change value Url. fn handleChangeValue get initialization query
query: {
field: '',
email: '',
}
does not value query updated.
here issues were you did not initialize the value of textfield and emailfield I updated code pls check now
export function HomePage() {
const [query, setQuery] = useState({
field:'',
email:''
});
const handleChaneValue = (value) => {
// not received data on change
console.log("query", query);
setQuery({
...query,
[value.sender.name]: value.newValue,
});
};
console.log("query2", query);
return (
<div>
<Container
padding={10}
platformConfig={{
desktop: {
maxWidth: 400,
},
}}
>
<FormPanel
padding={10}
shadow
defaults={{
errorTarget: "under",
}}
margin="0 0 20 0"
title="Using Validators"
>
<Textfield
required
label="Required Field"
requiredMessage="This field is required."
errorTarget="under"
name="field"
onChange={handleChaneValue}
value={query.field}
/>
<EmailField
label="Email"
validators="email"
errorTarget="under"
name="email"
value={query.email}
onChange={handleChaneValue}
/>
<Container layout="center">
<Button
ui="confirm"
text="BTN submit"
handler={handleClick}
style={{ border: "1px solid black" }}
/>
</Container>
</FormPanel>
</Container>
</div>
);
}
export default HomePage;
I found the solution to the problem. I using framework ExtReact so when run function, states re-initialized initil value. To solve this problem you can useRef and refer here.
enter link description here

Cannot pass the fetch method information to the instance data

When I run the below code, the values inside the currencie variable are not displayed.
I cannot pass the fetch method information to the instance data. I would like to fetch the data and display it on the screen. If I use console.log I can see the data as expected.
<template>
<Page class="page">
<ActionBar title="Tela N°1" class="action-bar" />
<ScrollView>
<StackLayout class="home-panel">
<!--Add your page content here-->
<Label textWrap="true" text="Primeira tela criada usando NativeScript"
class="h2 description-label" />
<Button text="Segunda Tela" #tap="onButtonTap" />
<Button text="Terceira Tela" #tap="onButton" />
<ListView class="list-group" for="currencie in currenciess"
style="height:1250px">
<v-template>
<FlexboxLayout flexDirection="row" class="list-group-item">
<Label :text="currencie.name" class="list-group-item-heading" style="width: 60%" />
<Label :text="currencie.buy" class="list-group-item-heading"
style="width: 60%" />
</FlexboxLayout>
</v-template>
</ListView>
</StackLayout>
</ScrollView>
</Page>
</template>
<script>
import Second from "./Second";
import Third from "./Third";
const http = require("tns-core-modules/http");
const url = "https://api.hgbrasil.com/finance?key=c5239f9c";
export default {
data() {
return {
currenciess: []
};
},
mounted() {
fetch(url)
.then(response => response.json())
.then(results => {
this.currenciess = results.results.currencies.USD;
});
},
};
</script>
Change your mounted method. currenciess is an array while your results.results.currencies["USD"] is an object coming from API. I have created a playground for you here.
mounted() {
console.log("mounted");
fetch(url)
.then(response => response.json())
.then(results => {
this.currenciess.push(results.results.currencies["USD"]);
});
}

Editing a Material UI row within React + Redux

I have a material UI table in a react project, and I want a user to click on the pencil/Edit Icon to edit the table row.
This is a loaded question, but would this require an additional piece of Material UI? what would the logic look like to make this happen?? I have most of the code set up on the backend, but don't know how to write this code in the component???
Thanks for looking!
//STYLE VARIABLE BOR MATERIAL BUTTON
const style = {
margin: 12
//
};
const mapStateToProps = (state) => ({
user: state.user,
reduxState: state.getExpense
});
class ExpenseTable extends Component {
constructor(props) {
super(props);
this.state = {
getExpense: []
};
}
isSelected = (index) => {
return this.state.selected.indexOf(index) !== -1;
};
handleRowSelection = (selectedRows) => {
this.setState({
selected: selectedRows,
});
};
//on page load, DISPATCH GET_EXPENSE is
//SENT TO expenseSaga which then
//goes to getExpenseReducer and appends EXPENSE_DATA to the
//DOM
componentDidMount() {
const { id } = this.props.match.params;
this.props.dispatch({ type: USER_ACTIONS.FETCH_USER });
this.props.dispatch({ type: 'GET_EXPENSE' });
}
componentDidUpdate() {
if (!this.props.user.isLoading && this.props.user.userName ===
null) {
this.props.history.push('home');
}
}
logout = () => {
this.props.dispatch(triggerLogout());
// this.props.history.push('home');
};
//SETS STATE FOR ALL INPUTS
handleChange = (name) => {
return (event) => {
this.setState({
[name]: event.target.value
});
};
};
//SUBMIT BUTTON- TRIGGERS DISPATCH TO EXPENSE SAGA TO ADD DATA
handleClick = () => {
console.log('add expense', this.state);
this.props.dispatch({
type: 'ADD_EXPENSE',
payload: this.state
});
};
//TRASH ICON-TRIGGERS DISPATCH TO EXPENSE SAGA DELETE
handleClickRemove = (id) => {
console.log('delete expense', this.state);
this.props.dispatch({
type: 'DELETE_EXPENSE',
payload: id
});
};
handleClickEdit = (row) => {
console.log('edit expense', this.state)
this.props.dispatch({
type: 'EDIT_EXPENSE',
payload: row
})
}
render() {
console.log('HEY-oooo expense render', this.state);
let content = null;
if (this.props.user.userName) {
//MAP OVER REDUX STATE.
const tableRows = this.props.reduxState.map((row) => {
//.MAP SEPARATES DATA INTO INDIVIDUAL ITEMS.
const { id, item_description, purchase_date,
item_price, item_link } = row;
return (
<TableRow selectable={false}>
{/* TABLE ROWS */}
<TableRowColumn>{item_description}
</TableRowColumn>
<TableRowColumn>{purchase_date}
</TableRowColumn>
<TableRowColumn>${item_price}</TableRowColumn>
<TableRowColumn><a href={item_link}>{item_link}
</a></TableRowColumn>
<TableRowColumn><EditIcon class="grow:hover"
onClick={() => {this.handleClickEdit(row)}} />
</TableRowColumn>
<TableRowColumn><TrashIcon onClick={() =>
{this.handleClickRemove(id);
}}/>
</TableRowColumn>
</TableRow>
// END TABLE ROWS
);
});
<div>
{/* FORM FOR ADDING EXPENSES(DATA) */}
<form id="expenseForm">
<h3>
Add a new <br />
expense
</h3>
<input
type="text"
id="fname"
name="fname"
placeholder="Item description"
onChange=
{this.handleChange('item_description')}
/>
<br />
<br />
<input
type="text"
id="lname"
name="lname"
placeholder="Item price"
onChange={this.handleChange('item_price')}
/>
<br />
<input
type="text"
id="lname"
name="lname"
placeholder="Item link"
onChange={this.handleChange('item_link')}
/>
<br />
{/* END FORM */}
<RaisedButton
id="expSubmit"
label="Submit Expense"
primary={true}
style={style}
onClick={this.handleClick}
/>
{/* TABLE TOTAL KEEPS CURRENT TOTAL OF PRICE COLOUMN */}
<h1>Total:</h1>
<br />
<h3>$748.93</h3>
</form>
{/* TABLE HEADERS */}
<Table>
<TableHeader>
<TableRow>
<TableHeaderColumn>Item
description</TableHeaderColumn>
<TableHeaderColumn>Purchase
Date</TableHeaderColumn>
<TableHeaderColumn>Item
Price</TableHeaderColumn>
<TableHeaderColumn>Item
Link</TableHeaderColumn>
<TableHeaderColumn>Edit
entry</TableHeaderColumn>
<TableHeaderColumn>Delete
entry</TableHeaderColumn>
</TableRow>
</TableHeader>
<TableBody>
{tableRows}
</TableBody>
</Table>
</div>
);
}
return (
<div>
<Nav />
{content}
</div>
);
}
}
// this allows us to use <App /> in index.js
export default connect(mapStateToProps)(ExpenseTable);
The default material-ui table doesn't have the feature of in-line editing. You will have to write your own wrapper to achieve this which can be time consuming. To overcome the time issue we can use some good existing libraries.
Here's one powerful library from DevExtreme for the same which i used, but go through their licensing before you take the final decision to use.
https://devexpress.github.io/devextreme-reactive/react/grid/demos/featured/controlled-mode/