Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

Can't create a new event listener on a newly created jQuery object. Must use existing event listener on parent element.

I tried selecting a newly created element which for JS resulted in null and for jQuery did nothing at all. I could, however, select it through its parent element. Is this the way its supposed to be?

My code is as follows

//contact class


document.addEventListener('DOMContentLoaded', () => {
//create a class to create contacts
    class Contact {
        constructor(first_name, middle_name, last_name) {

            this.first_name = first_name
            this.middle_name = middle_name
            this.last_name = last_name
        }
    }



    //                //
    //Event Listeners//
    //                //


    $('.create').on('click', function (event) {
        event.preventDefault()
        if (event.target.textContent === 'Create contact') {
            createForm('.create')

        }
        if (event.target.textContent=== 'Submit'){

            alert('hello')
        }
    })

   //MY TWO ATTEMPTS TO CREATE EVENT LISTENERS ON THE NEWLY CREATED ELEMENTS//
   /*

    const button = document.querySelector('button')
    button.addEventListener('click', function () {
        alert('hello')
    })

    $('button').on('click',function(){
        alert('hello')
    })

    */



    //When the window loads, check if address book is empty.
    $(window).on('load', function () {

        if ($('.contact_list').find('li').length === 0) {
            $('.contact_list').append($('<p>There are no contacts listed</p>'))
        }

    })

    //creates form to input contact data
    function createForm(parentNode) {
        const form = "<form id = 'contact_form'><label>First Name </label><input><button class='create' type='submit'>Submit</button></form>"
        $(parentNode).append(form)

    }
    //uses data from form to create contact
    function createContact() {
        const first_name = $('input').val()
        const contact = new Contact(first_name, '', '')
    }
})

The relevant html

    <div class='create'>
        <h2>Create contact</h2>
    </div> 
    <div class = 'contact_list'>
            <h3>List of Contacts: </h3>
    </div>

1 Answer

Steven Parker
Steven Parker
242,296 Points

The "MY TWO ATTEMPTS" code is commented out, but it is also outside of the event handler.

So right now, if the comments were removed it would run when the DOM content was loaded, which is before any button has been created to attach a handler to.

You would also probably not want to use that kind of selector, since as each new button is added, additional listeners would be added to the buttons previously created.

Hey, so I commented those out just to show what I had tried to do. So I understand that the button object is created before it actually exists in the DOM, but when its actually called upon (via one of the 2 methods I commented out) should the program not look back at all the previously defined variables and find it? Thanks for your help.

Steven Parker
Steven Parker
242,296 Points

They would if you move them into the handler, but then you have the problem of multiple listeners.

On the other hand, this would be a good opportunity for a delegated handler:

  $(".create").on("click", "button", function() {
      alert("hello");
  });

This way, even buttons created later will be handled.

Sorry, when you said 'move them into the handler', does that not mean move them inside the event listener?

So basically my intention was to use jQuery to create a form with new elements which could eventually submit data to my functions and Classes?

I'm just still unclear why my 2 attempts at creating event listeners failed when the button variable is globally defined.

Steven Parker
Steven Parker
242,296 Points

The "handler" is the function you pass when you establish a listener. It's what runs when the event happens.

Your 2 attempts did not use a "button" variable, but they used selection methods (one with jQuery, one with "querySelector") to find the "button" element(s). The failure was due to the code running during the "DOMContentLoaded" event, which happened before the button(s) had been created. So at that moment there were no buttons to add listeners to.

My suggestion about using a delegated handler avoids the problem by setting up a listener that will respond to buttons that are created later.

Ok, so it seems that to add functionality to objects created later in the program, the general rule is that you must attach a delegated handler (or event listeners with if statements) to existing parent nodes. Thanks again for helping clear this up.

Steven Parker
Steven Parker
242,296 Points

It's not a "must" but it is usually convenient and efficient. You could also create individual handlers at the same time as you add the new elements.