Home > Mobile >  How to post mongoose objectId using axios to the frontend react-select from the backend
How to post mongoose objectId using axios to the frontend react-select from the backend

Time:11-27

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

CodePudding user response:

You have a few problems, both on front-end and back-end.
Try to change your component like this:

class Billing extends Component {
  constructor() {
    super();
    this.state = {
      clients: [],
      clientdetails: '',
      paymentReferenceCode: '',
      paymentType: '',
      paymentDescription: '',
      procedureAmount: '',
      paymentDiscount: '',
      AmountPaid: '',
      Total: '',
    };
    this.handleSubmit = this.handleSubmit.bind(this);
    this.handleChange = this.handleChange.bind(this);
    this.handleChangeClientDetails = this.handleChangeClientDetails.bind(this);
  }

  componentDidMount() {
    this.loadData();
  }

  handleChange(event) {
    this.setState({
      ...this.state,
      [event.target.name]: event.target.value,
    });
  }

  handleChangeClientDetails(newValue) {
    this.setState({
      ...this.state,
      clientdetails: newValue._id
    })
  }

  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({
          ...this.state,
          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,
    };
    if (!this.state.clientdetails) {
      console.log('Select client');
      return;
    }
    axios.post(`http://localhost:4000/Bill/addbill/${this.state.clientdetails}`, entry).then((response) => {
      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.clients}
                filterOption={this.customFilter}
                isClearable={true}
                search={true}
                components={{ IndicatorSeparator: () => null }}
                placeholder={'Select Client'}
                getOptionLabel={(option) => `${option.fullName} ${option._id}`}
                onChange={this.handleChangeClientDetails} />
              ...
          </div>
        </div>
      </div>
    );
  }
}

export default Billing;

And add the parameter to the POST route:

router.post("/addbill/:id", ... );

CodePudding user response:

At your router you're using req.params.id but it's never declared, since your clientdetails uses the clientid, it'll be null. Easy to fix.

router.post("/addbill",async(req,res)=>{
    try {
        console.log(req.params);        
        const clientid = await clients.findOne({ _id: req.params.id });

should be

//                    /-- req.params.id
router.post("/addbill/:id",async(req,res)=>{
    try {
        console.log(req.params);        
        const clientid = await clients.findOne({ _id: req.params.id });

just remember that now your route will need the /clientid at the end.

  • Related