How to make the get method read the url with params on button click using NodeJS, Express, and Mongoose

Viewed 101

I'm trying to show the data from DB in a table by list of cities. These cities are contained in a select option. Using form = get method I was able to get the value of the cities in the URL when I select a city then click the submit button inside my form. However, I think my router.get(/:city) does not read the URL with the city value on it for my table.ejs does not get rendered on the UI. How do I make my get method read my url with param on button click?

This is the screenshot of the URL on button click

enter image description here

This is my index.ejs file

<form method="GET">
    <div class="col">
      <div class="mb-3 row">
        <label class="col-md-4 col-sm-4 col-lg-2 col-form-label fs-6">Category:</label>
        <div class="col-md-4 col-sm-4 col-lg-7">
            <select class="form-select form-select-sm mt-1" id="selectCity" name="city">
              <option selected>Select a city...</option>
              <option name= "Manila" value="Manila">Manila</option>
              <option name= "Quezon City" value="Quezon City">Quezon City</option>
              <option name= "Pasig" value="Pasig City">Pasig City</option>
            </select>
        </div>
  
        <div class="col-md-4 col-sm-4 col-lg-3">
          <button type="submit" class="btn btn-sm btn-outline-primary mt-1" id="getCity">Show</button>
        </div>
      </div>            
    </div>
  </form>

This is my routes.js get method section.

//Homepage
router.get("/", function(req, res){
res.render('index')});

//Display data in table by city
router.get("/:city", function(req, res){
const city = req.params.city;
CityModel.find()
    .then(result => {
        res.render('table', {vaccines:result});
        //console.log({vaccines:result});
    })
    .catch(err => {
        res.status(500).send({message: "Cannot display data!"});
        console.log(err);
    })});

As you can see I was not able to use the city param yet for I want to make the unfiltered table with all the data appear first when I click the Show button. I was able to do this with the :id param but when I try with other fields in my DB it does not work.

2 Answers

Its not really clear what you are trying to do here or maybe I'm reading it wrong but I think what you want to do is to make the city param optional so update your route like this

router.get("/:city?", function(req, res){

The question mark means it may or may not be there, then in your code block check if its there, otherwise query everything

then in your get you would check if there is a param, if not use get everything, otherwise use the city param

if ( req.params.city) {
//its not undefined, use the param
}else{
//nothing was passed, grab everything
} 

I found out my error. I didn't indicate an action in my form tag that's why my get method does not work properly. By adding form method="Get" action="/vaccines", I was able to properly call my get method and get the selected city value.

<form method = "GET" action= "/vaccines">
  <div class="col">
    <div class="mb-3 row">
      <label class="col-md-4 col-sm-4 col-lg-2 col-form-label">Category:</label>
      <div class="col-md-4 col-sm-4 col-lg-7">
          <select class="form-select form-select-sm mt-1" id="selectCity" name="city">
            <option name="">Select a city...</option>
            <option name= "Manila" value="Manila">Manila</option>
            <option name= "Quezon City" value="Quezon City">Quezon City</option>
            <option name= "Pasig" value="Pasig">Pasig</option>
          </select>
      </div>

      <div class="col-md-4 col-sm-4 col-lg-3">
        <input class="btn btn-sm btn-outline-primary mt-1" type="submit" value="&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Show&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" id="showCityBtn">
      </div>
    </div>            
  </div>
</form>

I have also incorporated the suggestion of proxim0 to make city optional in the url for get method.

//Homepage
router.get("/", function(req, res){
CityModel.find()
.then(result => {
    res.render('index', {vaccines:result});
    //console.log({vaccines:result});
})
.catch(err => {
    res.status(500).send({message: "Cannot display data!"});
    console.log(err);
})
});


//Display data in table by city
router.get("/vaccines/:id?", function(req, res){
if (req.params.id){
    const id = req.params.id;
    const vaccineDisp = new CityModel({
    city: req.query.city,
    vaccine: req.query.vaccine,
    supply: req.query.supply,
    firstDosed: req.query.firstDosed,
    fullyDosed: req.query.fullyDosed,
    expiration: req.query.expiration
})

CityModel.findById(id)
.then(result => {
    res.render('update_vacc', {vaccineDisp: result});
    console.log('Data to be updated:');
    console.log({vaccineDisp:result})
})
.catch(err => {
    res.status(500).send({message: "Cannot display data!"});
    console.log(err);
})
} else {
    const getCity = req.query.city;
    CityModel.find({city: getCity})
    .then(result => {
        res.render('index', {vaccines:result});
        //console.log({vaccines:result});
    })
    .catch(err => {
        res.status(500).send({message: "Cannot display data!"});
        console.log(err);
    })
}

});

Thank you so much!

Related