I have a simple backend code which works well with Rest API
updated code
ClientSchema.js
const mongoose = require('mongoose');
var Schema = mongoose.Schema;
const customerSchema = new Schema({
paymentReferenceCode:{
type: String,
required: true
},
paymentType:{
type: String,
required: true
},
paymentDescription:{
type: String,
required: true
},
procedureAmount:{
type: String,
required: true
},
paymentDiscount:{
type: Number,
required: true
},
AmountPaid:{
type: Number,
required: true
},
Total:{
type: Number,
required: true
},
clientdetails: {
ref: 'Client',
type: mongoose.Schema.Types.ObjectId
},
}, { timestamps: true })
module.exports = mongoose.model('Customer',customerSchema);
Client.js
const mongoose = require('mongoose');
const ClientSchema = new mongoose.Schema({
fullName:{
type:String,
required: true
},
dateofBirth:{
type:Date,
required: true
},
gender:{
type:String,
required: true
},
nationality:{
type:String,
required: true
},
address:{
type:String,
required: true
},
date:{
type:Date,
default:Date.now
}
});
module.exports = mongoose.model('Client', ClientSchema)
Router.js
router.post("/addbill",async(req,res)=>{
try {
console.log(req.params);
const clientid = await clients.findOne({ _id: req.params.id });
await new Customer({
clientdetails:clientid,
paymentReferenceCode:req.body.paymentReferenceCode,
paymentType:req.body.paymentType,
paymentDescription:req.body.paymentDescription,
procedureAmount:req.body.procedureAmount,
paymentDiscount:req.body.paymentDiscount,
AmountPaid:req.body.AmountPaid,
Total:req.body.Total
}).save(async (err, data) => {
if (err) {
console.log('err:', err);
res.status(500).json({
message: 'Something went wrong, please try again later.'
});
} else {
res.status(200).json({
message: 'Bill Created',
data,
id: data._id
});
}
});
} catch (error) {
res.status(422).json(error);
}
})
router.get('/', async (req, res) => {
try{
const data = await clients.find();
res.json(data)
}
catch(error){
res.status(500).json({message: error.message})
}
})
Frontend
Billing.js
import React, {Component } from "react";
import "bootstrap/dist/css/bootstrap.min.css"
import axios from "axios"
import SimpleReactValidator from "simple-react-validator"
import TextField from '@mui/material/TextField';
import $ from 'jquery'
import Select,{components} from "react-select";
import Box from '@mui/material/Box';
import NativeSelect from "@mui/material/NativeSelect";
import Button from "@mui/material/Button";
class Billing extends Component {
constructor(){
super()
this.state = {
clientdetails :{},
paymentReferenceCode: "",
paymentType: "",
paymentDescription: "",
procedureAmount: "",
paymentDiscount: "",
AmountPaid: "",
Total: "",
}
this.changePaymentReferenceCode = this.changePaymentReferenceCode.bind(this)
this.changePaymentType = this.changePaymentType.bind(this)
this.changePaymentDescription = this.changePaymentDescription.bind(this)
this.changeProcedureAmount = this.changeProcedureAmount.bind(this)
this.changePaymentDiscount = this.changePaymentDiscount.bind(this)
this.changeAMountPaid = this.changeAMountPaid.bind(this)
this.changeTOtal = this.changeTOtal.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
this.handleChange = this.handleChange.bind(this)
}
changePaymentReferenceCode(event){
this.setState({
paymentReferenceCode:event.target.value
})
}
changeProcedureAmount(event){
this.setState({
procedureAmount:event.target.value
})
}
changePaymentType(event){
this.setState({
paymentType:event.target.value
})
}
changePaymentDescription(event){
this.setState({
paymentDescription:event.target.value
})
}
changePaymentAmount(event){
this.setState({
paymentAmount:event.target.value
})
}
changePaymentDiscount(event){
this.setState({
paymentDiscount:event.target.value
})
}
changeAMountPaid(event){
this.setState({
AmountPaid:event.target.value
})
}
changeTOtal(event){
this.setState({
Total:event.target.value
})
}
handleChange(event) {
this.setState({
[event.target.name]: event.target.value
})
}
componentDidMount(){
this.loadData();
}
loadData = () => {
axios.get('http://localhost:4000/clients', {
headers: {"Access-Control-Allow-Origin": true,
'Access-Control-Allow-Credentials' : true,
'Access-Control-Allow-Methods':'GET,PUT,POST,DELETE,PATCH,OPTIONS',
crossorigin : true,
},
responseType : 'json'
})
.then((result) => {
console.log(result.data);
this.setState({
clients : result.data,
})
})
.catch((error) => {
console.log(error);
})
}
customFilter = (option, searchText) => {
if(
option.data.fullName.toLowerCase().includes(searchText.toLowerCase())
)
return true;
return false;
}
handleSubmit(event){
event.preventDefault()
const entry = {
paymentReferenceCode: this.state.paymentReferenceCode,
paymentType: this.state.paymentType,
paymentDescription: this.state.paymentDescription,
procedureAmount: this.state.procedureAmount,
paymentDiscount: this.state.paymentDiscount,
AmountPaid: this.state.AmountPaid,
Total: this.state.Total,
}
axios.post('http://localhost:4000/Bill/addbill', entry)
.then(response => {
this.setState({clientdetails: response.data})
console.log(response.data)
})
this.setState({
clientdetails:{},paymentReferenceCode: "",paymentType: "",paymentDescription: "",procedureAmount: "",
paymentDiscount: "",AmountPaid: "",Total: "",
})}
render() {
const displayNone = { display: 'none' }
return (
<div>
<div className="container">
<div className="form-div">
<p className="text-capitalize">Billing</p>
<Box component="form" onSubmit={this.handleSubmit} noValidate sx={{ mt: 1}}>
<Select
closeMenuOnSelect={true}
hideSelectedOptions={true}
options={this.state.clientdetails}
filterOption = {this.customFilter}
isClearable={true}
search={true}
components={{IndicatorSeparator: () => null,}}
placeholder={'Select Client'}
getOptionLabel={option => `${option.fullName} ${option._id}`}
onchange={this.customFilter}
></Select>
<TextField
margin="normal"
fullWidth
id="paymentReferenceCode"
label="PaymentRefernceCode"
name="paymentReferenceCode"
autoComplete="off"
value={this.state.paymentReferenceCode}
onChange={this.handleChange}
autoFocus
/>
<NativeSelect
fullWidth
onChange={this.handleChange}
value={this.state.paymentType}
inputProps={{
name: 'paymentType',
id: 'paymentType',
}}
>
<option >PaymentType</option>
<option value="Cash">Cash</option>
<option value="PayPal">PayPal</option>
<option value="MasterCard">MasterCard</option>
</NativeSelect>
<TextField
margin="normal"
fullWidth
InputLabelProps={{style : {color : 'black'} }}
id="paymentDescription"
label="Payment Description"
name="paymentDescription"
autoComplete="paymentDescription"
onChange={this.handleChange}
value={this.state.paymentDescription}
autoFocus
/>
<TextField
margin="normal"
fullWidth
id="AmountPaid"
label="Amount Paid"
name="AmountPaid"
autoComplete="AmountPaid"
onChange={this.handleChange}
value={this.state.AmountPaid}
autoFocus
/><TextField
margin="normal"
fullWidth
id="paymentDiscount"
label="Payment Discount"
name="paymentDiscount"
autoComplete="paymentDiscount"
onChange={this.handleChange}
value={this.state.paymentDiscount}
autoFocus
/>
<TextField
margin="normal"
fullWidth
id="procedureAmount"
label="Procedure Amount"
name="procedureAmount"
autoComplete="procedureAmount"
onChange={this.handleChange}
value={this.state.procedureAmount}
autoFocus
/>
<TextField
margin="normal"
fullWidth
id="Total"
label="Total Bill"
name="Total"
autoComplete="Total"
onChange={this.handleChange}
value={this.state.Total}
autoFocus
/>
<div id='loginSuccess' className="alert alert-success" style={displayNone} role="alert">
<strong>Success! </strong>Client Bill Entered Successful.
</div>
<Button
type="submit"
fullWidth
sx={{ mt: 3, mb: 2}}
>
<span className='btn btn-warning btn-block form-control form-group'>Submit</span>
</Button>
</Box>
</div>
</div>
</div>
);
}
}
export default Billing;
I tried to use axios.post and submit the form. However, am not able to retrieve clientdetails data to the frontend in particular the select part of the form, it returns null. But the other entries go through to the backend. This is what am getting in the console.
data:
AmountPaid: 100
Total: 100
createdAt: "2022-11-25T22:31:57.306Z"
clientdetails: null
paymentDescription: "accomodation"
paymentDiscount: 100
paymentReferenceCode: "2345"
paymentType: "Cash"
procedureAmount: "3"
updatedAt: "2022-11-25T22:31:57.306Z"
__v: 0
_id: "6381425db019f3f9a48047ae"
[[Prototype]]: Objectid: "6381425db019f3f9a48047ae"
I would like to retrieve the clientdetails data to the frontend select section, select an option and be able to submit all the data.Thank you
2
Answers
At your router you’re using
req.params.id
but it’s never declared, since yourclientdetails
uses theclientid
, it’ll benull
. Easy to fix.should be
just remember that now your route will need the
/clientid
at the end.You have a few problems, both on front-end and back-end.
Try to change your component like this:
And add the parameter to the POST route: