1. Advertising
    y u no do it?

    Advertising (learn more)

    Advertise virtually anything here, with CPM banner ads, CPM email ads and CPC contextual links. You can target relevant areas of the site and show ads based on geographical location of the user if you wish.

    Starts at just $1 per CPM or $0.10 per CPC.

dynamically pass parameter in js inside dynamically created <div>

Discussion in 'jQuery' started by sjsantana, Dec 12, 2021.

  1. #1
    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 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.
    SEMrush
    
    <script type="text/javascript" >
    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 += `
    <!-- Book Now button -->
    <div class="d-flex justify-content-end mt-1">
    <div class="btn btn-primary text-uppercase" id="bookingBtn" data-hotel-id="${hotel.id}">Book Now</div>
    </div>
    </div>`;
    });
    document.getElementById('output').innerHTML = output;})
    }
    
    $('body').on('click', 'bookingBtn', function() {
    
    let hotelId = $(this).data('hotel-id')
    console.log("Hotel id is " + hotelId);
    fetch('http://localhost:8080/hotels/' + hotelId + '/booking-form', {
    method: 'POST'
    })
    });
    
    
    Code (markup):
     
    sjsantana, Dec 12, 2021 IP
    SEMrush
  2. sarahk

    sarahk iTamer Staff

    Messages:
    27,849
    Likes Received:
    4,319
    Best Answers:
    123
    Trophy Points:
    665
    #2
    Initial problem is that id of the new button is always the same, it needs to include the hotel.id as well... although it doesn't need to be an id, it could be a class which would then mean your listener would be like this:

    $('body').on('click', '.bookingBtn', function()

    I'm very curious about why you use the text-uppercase class when you have total control over the content of that div. What's the reason?

    Here's my version - still some more things I'd do differently but it works
    $("#showAll").on("click", showAll);
    
    async function showAll() {
      console.log("showAll");
      let json = await getHotelInfo();
     
      console.log("buildButtons");
      console.log(json);
    
      let output = '<h2> Search Results </h2>';
      json.forEach(hotel=> {
        console.log(hotel.author);
        output += "<!-- Book Now button -->";
        output += '<div class="d-flex justify-content-end mt-1">';
        output +=
          '<div class="btn btn-primary bookingBtn" data-hotel-id="${hotel.id}">BOOK NOW ${hotel.id}</div>';
        output += "</div>";
        output += "</div>";
      });
      document.getElementById("output").innerHTML = output;
      $(".bookingBtn").on("click", clickBookingButton);
    }
    
    async function getHotelInfo() {
      console.log("getHotelInfo");
      let response = await fetch("https://picsum.photos/v2/list");
      return await response.json();
    }
    
    $("body").on("click", "bookingBtn", clickBookingButton);
    
    function clickBookingButton() {
      let hotelId = $(this).data("hotel-id");
      console.log("Hotel id is " + hotelId);
      fetch("http://localhost:8080/hotels/" + hotelId + "/booking-form", {
        method: "POST"
      });
    }
    
    Code (JavaScript):
     
    sarahk, Dec 12, 2021 IP
  3. sjsantana

    sjsantana Peon

    Messages:
    2
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    1
    #3
    Hi,
    After long hours of searching for the mistake it finally worked when I changed it to .btn-primary. As for your question - this was a bootstrap snippet which I am using for my project (I am studying Java). I will check out your version, it looks more sophisticated :)Thanks.
     
    sjsantana, Dec 13, 2021 IP
  4. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,615
    Likes Received:
    1,964
    Best Answers:
    248
    Trophy Points:
    515
    #4
    Right out of the gate, using a DIV for a BUTTON is inaccessible crap since it's non-keyboard navigable. ANYONE telling you it's ok to put "onclick" on anything other than anchors and field elements is packing your fudge.

    Second, innerHTML? Wrapping DIV for nothing? But of course both are to be expected when it looks like some sort of dipshit front-end CSS framework is involved... as well as the equally mentally enfeebled TRASH that is jQuery. Just like the fetch/then rubbish devoid of error handling.

    Also this is 2021 not 2009, you can stop saying type="text/javascript" on script tags.

    Not 100% certain what you're trying to accomplish, but I'm 100% sure that's not how one should go about it.
     
    deathshadow, Dec 16, 2021 IP
    sarahk likes this.
  5. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,615
    Likes Received:
    1,964
    Best Answers:
    248
    Trophy Points:
    515
    #5
    HEre's how I'd approach that. Untested, probably has typo's. Driveby post on the laptop, and I can't type worth **** on anything other than a Model M.

    
    {
    	const
    		output = document.getElementById("output"),
    		write = (tagName, content) => {
    			let element = output.appendChild(document.createElement(tagName);
    			element.textContent = content;
    			return element;
    		},
    		clickBooking = (event) => {
    			console.log("Hotel Id is " + event.currentTarget.id;
    			let x = new XMLThhpRequest();
    			x.responseType = "json";
    			x.open("post", "http://localhost:8080/hotels/" + event.currentTarget.id);
    			x.send();
    		};
    
    	document.getElementById("showAll").addEventListener("click", (e) => {
    		output.textContent = "";
    		write("h2", "Search Results");
    		let x = new XMLThhpRequest();
    		x.addEventListener('load', (event) => {
    			if (not this.status == 200) console.log("Faild AJAX Request - Code ", this.status);
    			else for (let hotel of this.response) {
    				let button = write("button", "Book Now");
    				button.type = "button"; // remember, default is submit!
    				button.value = hotel.id;
    				button.onclick = clickBooking;
    			}
    		});
    		x.responseType = "json";
    		x.open("post", "http://localhost:8080/accommodations");
    		x.send();
    	});
    
    }
    Code (markup):
    The outer {} provides scope isolation (replacing what we used to do wtth IIFE), I used XMLHttpRequest to simplify the logic and leverage responseType's auto-parsing into "event.response",

    Wondering how badly I goofed this, I've been so busy ripping scripting out of websites, I may have forgotten some basics.
     
    Last edited: Dec 16, 2021
    deathshadow, Dec 16, 2021 IP
    sarahk likes this.
  6. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,615
    Likes Received:
    1,964
    Best Answers:
    248
    Trophy Points:
    515
    #6
    And I did goof on the laptop.

    		clickBooking = (event) => {
    			console.log("Hotel Id is " + event.currentTarget.id;
    			let x = new XMLThhpRequest();
    			x.responseType = "json";
    			x.open("post", "http://localhost:8080/hotels/" + event.currentTarget.id);
    			x.send();
    		};
    
    Code (markup):
    Should be:
    
    		clickBooking = (event) => {
    			console.log("Hotel Id is " + event.currentTarget.value;
    			let x = new XMLThhpRequest();
    			x.responseType = "json";
    			x.open("post", "http://localhost:8080/hotels/" + event.currentTarget.value);
    			x.send();
    		};
    
    Code (markup):
    A big advantage of using a button? You can store the value on the button. On top of the fact it's keyboard navigable unlike DIV.
     
    deathshadow, Dec 16, 2021 IP
    sarahk likes this.