0

I am trying to build an appointment booking website using express, ejs and MongoDB. When request is sent to '/booking', book page is displayed with all the details of the doctor . For every doctor on clicking on book button, a form is added dynamically. A js event is added to the book button so that when the user clicks on that button, that particular doctor id can be accessed and sent back to server using ajax.My basic idea i was to the value of 'i' when the button is clicked and get the doctor_id value at that particular 'i' index from doctprs array. But ejs will get loaded before javascript so I am not able to do that. Please help me get the value of the selected doctor_id.

Update Inside the form in the div id="myCalendar" I am displaying a calendar from which a user can select the date. I want to get the doctor_id which the user selected and then send it using a axios request to the server and then get the time slots of that particular doctor on that particular date and display it in the form so that the user can select a particular time slot and book an appointment on that day for that calendar.

app.js

app.get("/booking",function(req,res){
  Doctor.find().populate('doctor_id','name id').populate('hospital_id').then((doctors,err)=>{
    res.render("book",{doctor:doctors});
  }).catch(err=>   req.flash('error',"Something went wrong!Try again!"));
}); 
app.post("/time_slots",function(req,res){
 
  items=Appointment.find({doctor_id: mongoose.Types.ObjectId(req.body.doctor), appointment_date:new Date(req.body.app_date)}).then((slots,err)=>{
    let data=JSON.stringify(slots);
    console.log(req.body.doctor+" "+req.body.app_date);
    console.log(slots);
   return res.json({slots: data})
  }).catch(err=>   req.flash('error',"Something went wrong!Try again!"))
});

book.ejs

<% for(i=0;i<doctor.length;i++){ %>
  <div id="details<%= i %>">
   <%= doctor[i].doctor_id['id'] %>
   <%= doctor[i].doctor_id['name'] %>
   <%= doctor[i].speciality %>
   <%= doctor[i].experience %>
   <%= doctor[i].hospital_id.name %>
   <%= doctor[i].hospital_id.location %>
   <button  class="btn btn-success booking_btn" id="<%= i %>">Book</button>
   <br><br><br>
  </div>
   <% } %>  
<script>
 
 var buttons= document.getElementsByClassName("booking_btn");
 for(let i = 0; i <buttons.length; i++) {
   buttons[i].addEventListener("click", function() {

   var booking_form=` <form action="/booking" method="post" id="book-appointment-form">
    <div id="myCalendar" class="vanilla-calendar" value=""></div>
    <div id="boxes"></div>
    <button type="submit" class="btn btn-success">Confirm</button>
    </form>`
    document.getElementById("details"+i).insertAdjacentHTML( 'beforeend', booking_form);
    createCalendar();
    sendSelectedDate(i);
   })
 }

 function createCalendar(){
  calendarSet=true;
 myCalendar = new VanillaCalendar({
 selector: "#myCalendar",
 pastDates: false,
 availableWeekDays: [
   {day: 'monday'},
   {day: 'tuesday'},
   {day: 'wednesday'},
   {day: 'thursday'},
   {day: 'friday'}
 ], 
 datesFilter: true
});

}
 function sendSelectedDate(i){
  let date_selected = document.getElementById("myCalendar");
  document.getElementsByClassName("vanilla-calendar-body")[0].addEventListener("click", function(e) {
  e.preventDefault();
  var t=<%= doctor[i].doctor_id['id'] %>
  var d =new Date(date_selected.value).toLocaleDateString('ko-KR').slice(0, -1).replaceAll('. ','-');
  axios.post('/time_slots', {app_date: d,doctor: t}).then(function (response) {
    var $section = $('<div class="col-md-4"></div>');
  (JSON.parse(response.data.slots)).forEach(function(slot) {
    $section.append(`<button>${slot.time_slot}</button>`);
  });
  $('#boxes').html($section);
    }).catch(function(e) {
    console.log(e);
    console.log("Please try again later.");
  })
})
 }
</script>
  • One correction and one recommendation: Correction: You are assigning an `id` attribute in a loop `book-appointment-form`. Id attributes are intended to be unique. Recommendation: Use event delegation rather than many, many duplicate event handlers. Read [What is DOM event delegation?](https://stackoverflow.com/questions/1687296/what-is-dom-event-delegation) – Randy Casburn Feb 02 '21 at 14:15
  • Hey @RandyCasburn thank you for replying, I posted the full code now. – mamadgi aishwarya Feb 02 '21 at 14:42

2 Answers2

0

Ii would work if you assign the doctor id to the buttons in the loop, by using dataset:

  1. assign the doctor id to the button
<button class="btn btn-success booking_btn" data-doctor-id="<%= doctor[i].doctor_id['id'] %>" id="<%= i %>">Book</button>
  1. retrieve the doctor id and set as myCalendar data:
var doctorId = buttons[i].dataset.doctorId
var booking_form=` <form action="/booking" method="post" id="book-appointment-form">
<div id="myCalendar" class="vanilla-calendar" data-doctor-id="${ doctorId }"></div>
...
  1. consume the doctor id from sendSelectedDate method:
var t=date_selected.dataset.doctorId

book.ejs

<% for(i=0;i<doctor.length;i++){ %>
  <div id="details<%= i %>">
   <%= doctor[i].doctor_id['id'] %>
   <%= doctor[i].doctor_id['name'] %>
   <%= doctor[i].speciality %>
   <%= doctor[i].experience %>
   <%= doctor[i].hospital_id.name %>
   <%= doctor[i].hospital_id.location %>
   <button class="btn btn-success booking_btn" data-doctor-id="<%= doctor[i].doctor_id['id'] %>" id="<%= i %>">Book</button>
   <br><br><br>
  </div>
   <% } %>  
<script>
 
 var buttons= document.getElementsByClassName("booking_btn");
 for(let i = 0; i <buttons.length; i++) {
   buttons[i].addEventListener("click", function() {
   var doctorId = buttons[i].dataset.doctorId
   var booking_form=` <form action="/booking" method="post" id="book-appointment-form">
    <div id="myCalendar" class="vanilla-calendar" data-doctor-id="${ doctorId }"></div>
    <div id="boxes"></div>
    <button type="submit" class="btn btn-success">Confirm</button>
    </form>`
    document.getElementById("details"+i).insertAdjacentHTML( 'beforeend', booking_form);
    createCalendar();
    sendSelectedDate(i);
   })
 }

 function createCalendar(){
  calendarSet=true;
 myCalendar = new VanillaCalendar({
 selector: "#myCalendar",
 pastDates: false,
 availableWeekDays: [
   {day: 'monday'},
   {day: 'tuesday'},
   {day: 'wednesday'},
   {day: 'thursday'},
   {day: 'friday'}
 ], 
 datesFilter: true
});

}
 function sendSelectedDate(i){
  let date_selected = document.getElementById("myCalendar");
  document.getElementsByClassName("vanilla-calendar-body")[0].addEventListener("click", function(e) {
  e.preventDefault();
  var t=date_selected.dataset.doctorId
  var d =new Date(date_selected.value).toLocaleDateString('ko-KR').slice(0, -1).replaceAll('. ','-');
  axios.post('/time_slots', {app_date: d,doctor: t}).then(function (response) {
    var $section = $('<div class="col-md-4"></div>');
  (JSON.parse(response.data.slots)).forEach(function(slot) {
    $section.append(`<button>${slot.time_slot}</button>`);
  });
  $('#boxes').html($section);
    }).catch(function(e) {
    console.log(e);
    console.log("Please try again later.");
  })
})
 }
</script>
Heri Hehe Setiawan
  • 1,362
  • 1
  • 10
  • 14
-2

You can add the onclick event to every button individually like this:

<% for(i=0;i<doctor.length;i++){ %>
  <div id="details<%= i %>">
   <%= doctor[i].doctor_id['name'] %>
   <%= doctor[i].speciality %>
   <%= doctor[i].experience %>
   <%= doctor[i].hospital_id.name %>
   <%= doctor[i].hospital_id.location %>
   <button  class="btn btn-success booking_btn" id="<%= i %>" onclick="yourFunction(<%= i %>)" >Book</button>
   <br><br><br>
  </div>
<% } %>  
<script>
//Your function here
function yourFunction(i) {
    //Your code here
}
</script>
Uri
  • 1
  • 1
  • OP already does this in their code. They just take a different approach that you have. – Randy Casburn Feb 02 '21 at 14:11
  • In addition the OP's approach is better than your suggestion as the use of _in-line_ event handers is discouraged. – Randy Casburn Feb 02 '21 at 14:17
  • Hey thank you for your reply. I am able to access the i value, the problem is that I am not able to get t value(var t= ),because t value is loaded before clicking the button, i think it is because it is an ejs code so i get an error. – mamadgi aishwarya Feb 02 '21 at 14:29
  • I had the same issue in my website and it fixed the problem. – Uri Feb 02 '21 at 19:46
  • Hey @Uri I tried this, did not work for me, any other idea Uri? – mamadgi aishwarya Feb 03 '21 at 12:49
  • if you want to collect data from every individual tag you can use the `parent` attribute and pass it to the function, for example you could pass the `parent` tag and get its `id` attribute so you can use it in your function. – Uri Feb 04 '21 at 18:43