API called with button, but function does not recognize the attribute

API called with button, but function does not recognize the attribute
0

#1
(function() {
	"use strict";

	const getJokesButton = document.getElementById('getData');
	getJokesButton.addEventListener('click', getData);
	
	// fetch data from api
	function getData() {
		fetch('http://api.icndb.com/jokes/random/10')
		.then(function(res) {
			return res.json()
		}).then(function(data) {
			console.log(data.value);
		}).catch(function(err) {
			console.log(err)
		})
		
		fetch('https://api.icndb.com/jokes/random/10')
		.then(res => res.json() )
		.then(data => { 

			console.log(data);
			let result;
			data.value.forEach((joke) => {
				result +=
				`<li><input type="checkbox"> User title : ${joke.joke}</li>
				`;
				document.getElementById('list-of-jokes').innerHTML = result;
			})
		}).catch((err)=>console.log(err))
	}

	let defaultList = document.getElementById('list-of-jokes');
	let favorite = document.getElementById('favorites');

	$("input[type=checkbox]").change(function () {
	    let $this = $(this),
	        i = $this.closest('li').index(),
	        $target = $(favorite);
	   
	        if (!this.checked) {
	            $target = $(defaultList);
	        } else {
	            $this.data('idx', i);
	        }

	        var $targetLi = $target.find('li:eq(' + $this.data('idx') + ')');
	        if ($targetLi.length) {
	            $target.find('li:eq(' + $this.data('idx') + ')').before($this.closest('li'));
	        } else {
	            $target.append($this.closest('li'));
	        }
	});
})();

As you might see the checkboxes are only generated in HTML when the user clicks on the button. Only how could I tell javascript to run (“input[type=checkbox]”).change(function () only when the api is generated in HTML


#2

it’s an event listener, isn’t it? if the piece of html it targets wasn’t generated it simply has no possible event to run


#3

Yes, the list items will be generated by click, and after that it should bind the attribute checkbox


#4

The binding only happens once. If new elements are generated after the binding occurs, they won’t have the event listener bound to them. What you want to do is use event delegation. Attach the event listener to the closest parent of the checkboxes, then delegate to those inputs. In your case, it would seem to be

$("#list-of-jokes").on("click", "input[type=checkbox]", function(event) {
    // do stuff
});

This will bind the event listener only once, but each time you click anywhere on #list-of-jokes (this includes any of its children), the event will delegate to whichever input you actually clicked on, as if by some powerful magic.