1

I'm a JS self-learner. Currently jQuery. So please don't downgrade me. I made an age checker app. But the combination input type number + submit button only works after a page refresh. Is it possible to change the age after submitting it once and see the style changes without a page reload?

What I mean is that after loading the page, my app works only once. Then console log doesn't show any change in the input field and clicking submit.

      <div class="container">
      <form>
        <label for="age">Check your age</label>
        <input type="number" min="5" max="100" id="ageInput" onfocus="this.value=''">
        <input id="inpBtn" type="button" value="Submit">
      </form>
      <div id="underage">
        <p>You need to get older. You're underage.</p>
      </div>
      <div id="ofAge">
        <p>You are good to go.</p>
      </div>
        <div id="tooOld">
          <p>You are too old for this club</p>
        </div>

  let ageInput = document.querySelector("#ageInput").value;


  $(document).ready(function(){
    $("#inpBtn").click(function(){
  console.log(ageInput);

      if(ageInput < 18) {
        $("#underage").css("color", "red");
        console.log("under 18");
      } else if (ageInput >= 18 && ageInput < 80) {
        $("#ofAge").css("color", "green")
        console.log("good to go");
      } else {
        $("#tooOld").css("color", "gray")
        console.log("too old");
      }
    });
  });
TomDev
  • 285
  • 2
  • 13
  • 2
    I think you need to disable the default behavior, check [Stop form refreshing page on submit](https://stackoverflow.com/questions/19454310/stop-form-refreshing-page-on-submit) – Tamir Abutbul Sep 07 '22 at 19:41
  • Also `.click()` is deprecated .. Use `.on("#inpBtn", "click", function(){ ... })` – Zak Sep 07 '22 at 19:42
  • See how I handle form, submit event (not click), and canceling in a recent [answer](https://stackoverflow.com/a/72927267/3807365) – IT goldman Sep 07 '22 at 19:44
  • Listen for the [submit](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit_event) event and handle your logic from there. `$('form').on('submit', function(event) { })` – Emiel Zuurbier Sep 07 '22 at 19:44
  • @Zak just FYI, [`click()`](https://api.jquery.com/click) is in no way deprecated. Your use of `on()` is also invalid in that example. – Rory McCrossan Sep 07 '22 at 19:46
  • You need to check the value of `#ageInput` *inside* your click event handler, otherwise it will only ever contain the value the field has when the page loads. – Rory McCrossan Sep 07 '22 at 19:47
  • @RoryMcCrossan but the condition for #ageInput is within the even listener – TomDev Sep 07 '22 at 19:52
  • @TomDev but you're reading the value of `#ageInput` only once, whenever your page loads. You need to check the value whenever you click your button. – Emiel Zuurbier Sep 07 '22 at 19:57
  • @EmielZuurbier when I put my conditions into the body of your function it stopped working. I removed the click event because "submit" will be the event, right? – TomDev Sep 07 '22 at 20:07
  • @RoryMcCrossan [jQuery Migration to 3](https://github.com/jquery/jquery-migrate/blob/main/warnings.md#user-content-shorthand-deprecated-v3-jqmigrate-jqueryfnclick-event-shorthand-is-deprecated) -- *"Solution: Instead of .click(fn) use .on("click", fn). Instead of .click() use .trigger("click")."* -- In certain instances .. You will come across a console warning that `.click()` is deprecated .. – Zak Sep 07 '22 at 22:21
  • @Zak thanks I stand corrected. It should really be updated in the API docs too in that case. – Rory McCrossan Sep 08 '22 at 07:49
  • @RoryMcCrossan -- And I use `$(document).on("click","#element",function() {` because it listens to the document for a click .. Even if `#element` doesn't exist -- yet. Extremely useful, because you can still detect the document click, even if your element isn't there. I haven't experienced any overhead difference, but I assume since it's listening to every click, there might be some negligible overhead. – Zak Sep 08 '22 at 15:33
  • Agreed, however my previous comment regarding invalid use of `on()` was because you've put the selector first - it should be the event name – Rory McCrossan Sep 08 '22 at 15:34
  • Good catch! -- I would edit, but alas 5 min = permanent comment! Fingers moving faster than brain in that moment! – Zak Sep 08 '22 at 15:38

1 Answers1

2

The main issue in your code is that you only retrieve the value of #ageInput once, when the page loads. This means that when your click event occurs it will ignore the value the user typed in to the field.

Also note that as the error messages are hidden until required, you can set their colours once using CSS, and not in JS every time the event happens. Then your code becomes simpler as it just hides/shows the validation error as necessary.

Finally, when working with a form it's better practice to hook your logic to the submit event of the form. This allows users to submit the form using the return key of their keyboard, amongst other accessibility improvements. To stop the form actually being submit, call preventDefault() on the event that's passed to the handler as an argument.

Here's a working example with all the above points included:

jQuery($ => {
  let $ageInput = $("#ageInput");

  $("form").on('submit', e => {
    e.preventDefault();
    $('.error').hide(); 
      
    let ageInput = $ageInput.val();
    if (ageInput < 18) {
      $("#underage").show();
    } else if (ageInput >= 18 && ageInput < 80) {
      $("#ofAge").show();
    } else {
      $("#tooOld").show();
    }
  });
});
.error { display: none; }
#underage.error { color: red; }
#ofAge.error { color: green; }
#tooOld.error { color: gray; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<div class="container">
  <form>
    <label for="age">Check your age</label>
    <input type="number" min="5" max="100" id="ageInput" />
    <button type="submit">Submit</button>
  </form>
  <div class="error" id="underage">
    <p>You need to get older. You're underage.</p>
  </div>
  <div class="error"  id="ofAge">
    <p>You are good to go.</p>
  </div>
  <div class="error"  id="tooOld">
    <p>You are too old for this club</p>
  </div>
</div>
Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339