My JS function's not working

Hi guys, Im working on my personal porfolio & thinking to add some web behaviour on my contact page.

Here’s my html code:

<div class="contact-form">
                <h3>Leave a message:</h3>
                <input type="text" placeholder="Name">
                <input type="text" placeholder="Email">
                <input type="text" placeholder="Subject">
                <label for="email">
                    <textarea id="email" name="extra" cols="66" rows="7" placeholder="Message"></textarea>
                </label>
                <form>
                    <input type="submit" value="Send a message"/>
                </form>
            </div>

Here’s the JS code:

function sendButton() {     
let greeting = alert("Thank you for you message 😊." + " I'll get back to you soon!");
 }
 let sendMsg = document.querySelector("form");
 sendMsg.addEventListener("click", sendButton);

For some reasons, my JS code keep appearing error (“ Uncaught TypeError: Cannot read property ‘addEventListener’ of null ”). I double checked the code and still cannot figure out where i went wrong. Please help me debug this, thanks🙏

1 Like

Hey there,

So you’re not getting this?


Try checking that sendMsg isn’t null before adding the event listener:

if (sendMsg) {
  sendMsg.addEventListener("click", sendButton);
}
2 Likes

I think than you have to querySelect the input text element, no the form element (Sry for my bad english)

1 Like

The input elements should be part of the form. This way, we can access the fields within the form.

Then there are two things you can do:
add a click event to the submit button
or add a submit event to the form

I would go for the latter.

A normal form submission will trigger a new page load, when working with JS this is not desired. You should use preventDefault() to prevent this default event/new page load

The reason sendMsg might be null could because your JS is loaded before your form. The document renders from top to bottom, so if your JS code is before your html form, the form isn’t rendered yet, so JS can’t find it, resulting in null

you could place your script just before your body closing tag to overcome this problem. To be sure this is the problem, could you post your full code exactly as you currently have it?

Thank you for your insights :smiley:

I think the reason it did not run for me was that i put my JS file into separate one and link it into the html file.

I followed your advice, I removed the JS file, and place the JS code under <footer> section and it works!
Here’s the code:

<footer>
        <div>
            <p> Copyright 2020 Trang Vo. All Rights Reserved.</p>
            <p><i class="fas fa-code"></i> by Trang Vo.</p>
        </div>
    </footer>
    <script>
        let sendMsg = document.querySelector("form");
            sendMsg.addEventListener("click", sendBtn);

        function sendBtn(){
              alert("Thank you for your message, I'll be in touch soon!");
            }
    </script>
    
</body>
</html>

My question now is when should i put the JS code into separate file in order to make it work? I’m still a new bee to JavaScript and there;s still a lot to learn​😅 Thanks!

you can make a separate JS, but the same thing applies: when the external JS is found, that code/file is read first before the rest of the html code is executed

so then the link to your external JS file should simple be before your body closing tag

2 Likes

My question now is when should i put the JS code into separate file in order to make it work? I’m still a new bee to JavaScript and there;s still a lot to learn​😅 Thanks!

You can achieve this by either adding the defer attribute or the async attribute to your opening script tag after linking it to the HTML.
The defer attribute halts the execution of the script being loaded first, thus, all your HTML page will load first, and then after, any script.

Using the async attribute on the other hand will allow the HTML load while awaiting the script load and execution. However, the script will not wait for the entire page to finish loading as in defer, but it will immediately load whenever it becomes available.

< script defer > or < script async ></ script>