1

One of the problems I am experiencing at the moment is not being able to call a function in the onclick event of the submit button.

$(document).ready(function() {
  function validate() {
    var contactName = document.getElementById("contact-name").value;
    alert("Thank you " + contactName);
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
  <label for="name">NAME</label>
  <input id="contact-name" name="name" placeholder="Please enter your name..." type="text">
  <label for="email">EMAIL</label>
  <input id="contact-email" name="email" placeholder="Please enter your contact email..." type="text">
  <label for="email">MESSAGE</label>
  <textarea id="contact-message" name="message" placeholder="Please enter your message.."></textarea>
</form>

<button type="button" id="submit" onclick="validate();">SUBMIT MESSAGE</button>
Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
CoderAz
  • 89
  • 4
  • 12
  • 2
    Possible duplicate of [Why can I not define functions in jQuery's document.ready()?](https://stackoverflow.com/questions/1055767/why-can-i-not-define-functions-in-jquerys-document-ready) – Sebastian Simon Aug 24 '17 at 16:52
  • validate() is not getting called you're just defining it but never calling it – sudo Aug 24 '17 at 16:52
  • @SoumeshBanerjee It’s in the `onclick` attribute. – Sebastian Simon Aug 24 '17 at 16:55
  • First of all, that's not submit button and it's defined outside the form so it will not submit all the value on submit action. and you don't need to define validate() function inside document.ready. – nikunjM Aug 24 '17 at 17:08

3 Answers3

4

You should write the validate() function outside the $(document).ready as the onclick in binded when the DOM loads - while $(document).ready scopes the function.

This means the function is local to the closure and will not be visible globally if its written so inside $(document).ready.

See demo below:

function validate() {
  var contactName = document.getElementById("contact-name").value;
  alert("Thank you " + contactName);

}
<form>
  <label for="name">NAME</label>
  <input id="contact-name" name="name" placeholder="Please enter your name..." type="text">
  <label for="email">EMAIL</label>
  <input id="contact-email" name="email" placeholder="Please enter your contact email..." type="text">
  <label for="email">MESSAGE</label>
  <textarea id="contact-message" name="message" placeholder="Please enter your message.."></textarea>
</form>

<button type="button" id="submit" onclick="validate();">SUBMIT MESSAGE</button>
kukkuz
  • 41,512
  • 6
  • 59
  • 95
  • Well, you have described the problem correctly, but your solution is not really very good because it keeps the inline HTML event attribute (which is really the source of the problem in the first place). If the inline HTML is removed and modern event binding occurs in JavaScript (inside the `document.ready` scope), then all will be well. – Scott Marcus Aug 24 '17 at 17:09
  • @ScottMarcus hey, that is not a reason to down vote!! – kukkuz Aug 24 '17 at 17:11
  • Ohh well, sorry I assumed it was you – kukkuz Aug 24 '17 at 17:13
1

As others have mentioned, the issue here is the scope that the validate() function is defined in.

JavaScript is "lexically scoped", meaning that the location of a declaration determines from where it can be reached by other code.

Your validate function is declared (scoped to) inside the anonymous document.ready function. This means that the only place where validate can be "seen" is by other code that shares that scope. The onclick=validate() line is outside of that scope and that is why your function isn't being called.

However, instead of moving the validate() function outside of the document.ready() callback (thus making it global, which is a bad thing), you really should remove the onclick inline HTML event attribute as this is a bad practice (see this for several reasons why) and do the event binding in the script area. This approach will allow you to set up the event in the same scope as the validate() function and keep the HTML clean:

$(document).ready(function() {
  // Do your event binding in JavaScript, not as inline HTML event attributes:
  $("#submit").on("click", validate);

  // Now the event handler reference and the function are in the same scope
  function validate() {
    var contactName = document.getElementById("contact-name").value;
    alert("Thank you " + contactName);
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
  <label for="name">NAME</label>
  <input id="contact-name" name="name" placeholder="Please enter your name..." type="text">
  <label for="email">EMAIL</label>
  <input id="contact-email" name="email" placeholder="Please enter your contact email..." type="text">
  <label for="email">MESSAGE</label>
  <textarea id="contact-message" name="message" placeholder="Please enter your message.."></textarea>
</form>

<button type="button" id="submit">SUBMIT MESSAGE</button>

Here's a bit more on scope.

Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
-1

First, you should avoid inline handlers like that. Second, depending on the form submission process. You should have the button inside your <form> tags. Then add <form method="POST" action="/someurl/to/post/to">.

Otherwise, use jQuery and $.ajax() with a click event handler:

$('#submit').on('click', () {
  $.ajax({check properties in jquery api docs}, (result) => { 
      // do something 
    }, 
    (e) => { 
      // do something on error 
  })
})
Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
stevenlacerda
  • 1,187
  • 2
  • 9
  • 21
  • This doesn't really address the problem. Also, HTML5 allows for form elements to exist outside of the `form` element as long as those elements have the `form` attribute. – Scott Marcus Aug 24 '17 at 17:07
  • Sure, buttons can go anywhere, doesn't mean they should. – stevenlacerda Aug 24 '17 at 17:14
  • No, you misunderstand. It is perfectly legal and valid for a button to go outside of a `form`. It is not correct to say that they "should" go inside the form. – Scott Marcus Aug 24 '17 at 17:15