When passing parameter from template literal to function - undefined

Hello!
I have this script which dynamically creates divs. I would like to pass parameters to the controller and be able to visualize the booking form after clicking Book button.
I get hotelId as undefined.
I would really appreciate if someone tells me what I am doing wrong and how can I get the id and pass it to the controller.

                    document.getElementById('showAll').addEventListener('click', showAll);
                    function showAll() {
                        fetch('http://localhost:8080/accommodations')
                            .then(response => {
                                return response.json()
                            })
                            .then((data) => {
                                let output = `<h2> Search Results </h2>`;
                                data.forEach(function (hotel) {
                                    output += `
                                    <div class="d-flex justify-content-end mt-1">
                                        <div class="btn btn-primary text-uppercase" data-hotel-id='${hotel.id}'>Book Now</div>
                                    </div>
                                </div>`;
                                });
                                document.getElementById('output').innerHTML = output;
                            })
                    }

                    $('body').on('click', 'button.btn', function() {

                        let hotelId = $(this).data('hotel-id')
                        console.log("Hotel id is " + hotelId);
                        fetch('http://localhost:8080/hotels/' + hotelId + '/booking-form', {
                            method: 'POST'
                        })
                    });
         

                </script>

Hi @SJS,

console.log or console.dir are my first thoughts.

Taking the clicks out of the equation are you able to log the fetched data?

window.addEventListener('DOMContentLoaded', (event) => {

  fetch('http://localhost:8080/accommodations')
    .then(response => {
      return response.json()
    })
    .then((data) => {
      console.dir(data) // what does it show?

      let output = '<h2> Search Results </h2>'

      data.forEach(function (hotel) {
        console.dir(hotel) // what does this show? is there a hotel.id?

        output += `
        <div>
            <div class="d-flex justify-content-end mt-1">
                <div class="btn btn-primary text-uppercase" data-hotel-id='${hotel.id}'>Book Now</div>
            </div>
        </div>`
      })

      document.getElementById('output').innerHTML = output
    })
})

Just as an aside, your template string inside the foreach appears to be missing one opening div or has one too many closing divs.

Here is what I get on the first console.dir and on the second. I see that I am getting the id. As for the divs - there are some more at the top and I cut them not to make the code too long, so perhaps I missed to delete something. But I will check them again.

Well that’s positive.

So looking at the next section and trying another console.log

$('body').on('click', 'button.btn', function () {
  console.log(this) // are you able to see the element and the dataset attribute hotel-id?
  const hotelId = $(this).data('hotel-id')
  console.log('Hotel id is ' + hotelId)
  fetch('http://localhost:8080/hotels/' + hotelId + '/booking-form', {
    method: 'POST'
  })
})

Using button.btn I see that I get another button which I use to show all hotels in the current function.

 <button type="button" class="btn search-btn" id="showAll">Show All</button> 

Perhaps I am not calling the Book Now button correctly and it took the value of the show all button. I tried with btn-primary but it does not do anything, class="btn btn-primary booking-btn, I also tried adding an id but it didn’t do anything either.

replace with

const hotelId = $(this).attr('data-hotel-id')

As far as I remember, data() doesn’t see dynamically created data attributes

Actually, data() isn’t related to any attributes at all. It allows you to set and read properites of hidden meta-object associated with the DOM-element. This object initializes its properties from data-attributes when page is loaded, but it doesn’t connect with these attributes after that and doesn’t watch when new attributes appear on the page.

I changed it but when I click on the button nothing happens.
How can I call the Book Now button correctly in the function? Because I tried with button.btn which refers to another button and I was able to get in the function but when I changed to button.btn-primary it doesn’t do anything.

if your button has class="btn", then it’s selector is button.btn

Suggested change is for your original code, I’m not quite understand what you’re talking about button classes

After changing it to .btn-primary I am seeing an id.

Thank you, @rpg_digital, @veocode.

2 Likes

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.