0

I have a webpage with 3 radio buttons, Create, Update, and Suppress, and form with input fields and dropdown selectors. The form input fields and dropdown selectors visible to the user are dynamic based on which of the radio buttons is selected. My current code is demonstrating unexpected behavior when I refresh the page.

When I first browse to the page in debug, all 3 radio buttons' views are as expected, as far as the delete dropdown (deleteid) being hidden from view in all but the Suppress view. However, if I click refresh in the browser, it returns to the Create radio button (which is expected), but the delete dropdown suddenly appears on the Create page. Repeated refreshes demonstrate the same behavior, and the delete dropdown selector continues to appear on the Create page. Why is this happening?

Here is the code:

document.addEventListener('DOMContentLoaded', function() {

  $(document).ready(function() {
    $('.js-example-basic-single').select2();
  });

  // Hide show inputs
  $('input[type=radio][name=group]').change(function() {
    if (this.value == 'create') {
      $('#proid').hide();
      $('#deleteid').hide();
      $('.fields').show();
    } else if (this.value == 'update') {
      $('#proid').show();
      $('#deleteid').hide();
      $('#btnSearch').show();
      $('.fields').show();
    } else if (this.value == 'suppress') {
      $('#proid').show();
      $('#deleteid').show();
      $('#btnSearch').hide();
      $('.fields').hide();
    }
  });

});
<!doctype html>
<html>

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <link rel="stylesheet" type="text/css" href="css/style.css">
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-rc.2/css/materialize.min.css">
  <link href="https://fonts.googleapis.com/css?family=Open+Sans&display=swap" rel="stylesheet">
  <link href="https://cdn.jsdelivr.net/npm/select2@4.0.13/dist/css/select2.min.css" rel="stylesheet" />
</head>

<body class="body-custom">
  <div class="container">
    <div class="form">
      <div class="row">
        <form id="form" action="">
          <div class="row">
            <div class="type">
              <label>
                                    <input class="with-gap" name="group" value="create" type="radio" checked />
                                    <span>Create</span>
                                </label>
              <label>
                                    <input class="with-gap" name="group" value="update" type="radio" />
                                    <span>Update</span>
                                </label>
              <label>
                                    <input class="with-gap" name="group" value="suppress" type="radio" />
                                    <span>Suppress</span>
                                </label>
            </div>
          </div>
          <div id="proid" class="row">
            <div class="input-field col s11">
              <input id="profile_id" type="text" class="validate">
              <label for="profile_id">Profile ID</label>
            </div>
            <div class="input-field col s1">
              <a id="btnSearch" class="btn-floating btn-small waves-effect waves-light teal lighten-2"><i class="material-icons">search</i></a>
            </div>
          </div>
          <!-- Delete Reason -->
          <div id="deleteid" class="row">
            <div class="input-field col s12">
              <select class="js-example-basic-single" name="deletereason" id="deletereason">
                <option value="" disabled selected>Choose delete reason</option>
                <option value="1">Reason 1</option>
                <option value="2">Reason 2</option>
                <option value="3">Reason 3</option>
              </select>
            </div>
          </div>
          <div class="row fields">
            <div class="input-field col s12">
              <input id="name" name="name" type="text" class="validate">
              <label for="name">Name</label>
            </div>
          </div>
          <div class="row">
            <button class="btn waves-effect waves-light" type="submit" name="action">
                                Submit
                                <i class="material-icons right">send</i>
                            </button>
          </div>
        </form>
      </div>
    </div>
  </div>


  <script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js'></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-rc.2/js/materialize.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/select2@4.0.13/dist/js/select2.min.js"></script>
  <script src="js/script.js"></script>

</body>

</html>

EDIT 1: I should also highlight that if I switch to Update view, then switch back to Create view, the delete dropdown then is NOT on the Create view any longer. But as soon as I click Refresh, it comes back

Stpete111
  • 3,109
  • 4
  • 34
  • 74
  • 2
    Please remove `document.addEventListener('DOMContentLoaded', function () {` is is not needed at all when you have $(document).ready(function () { - move all functions inside that – mplungjan Mar 09 '20 at 17:31
  • Just a hint: If you hide/show a lot things, that will trigger a reflow every time. Try first to hide the parent object, then toggle the children and then show the parent again. This will only cause 2 reflows. – Kai Lehmann Mar 09 '20 at 19:33
  • @KaiLehmann hi, could you expand on that a bit? I'm still learning JS - when you say to hide the parent then toggle the children and show the parent again, how would this look in code? – Stpete111 Mar 09 '20 at 20:30
  • @Stpete111 I does not belongs specially to js but more how browsers work. Whenever you change the bounds of an object, the browser has to recalculate all dimensions in the body to show it correct. That's a reflow. If you do this 20 times in a row (hiding/showing things) It will reflow 20 times. With $('item1tohide).parent().hide() you first hides the parent (1 reflow). Then you can toggle the 20 children (0 reflows because the parent is hidden) and then show the parent again (1 reflow). check https://stackoverflow.com/questions/27637184/what-is-dom-reflow – Kai Lehmann Mar 09 '20 at 20:38
  • @KaiLehmann thanks for that, that's very helpful. In my code above, what is considered the parent? – Stpete111 Mar 09 '20 at 20:44
  • @Stpete111 if you are not sure, you can always use $('yourelement').parent().hide() before using $('yourelement').show() (or .hide()) and after that use $('yourelement').parent.show(). It best case all your elements share the same parent. In worst case you have exactly the same number of reflows as with the original code – Kai Lehmann Mar 09 '20 at 20:55
  • @KaiLehmann makes sense, thank you for your input on this! – Stpete111 Mar 09 '20 at 21:30

1 Answers1

2

Try this.

Remove document.addEventListener('DOMContentLoaded', function () { is is not needed at all when you have $(document).ready(function () { - move all functions inside that

const checkRads  = () => {
  const checked  = $('input[type=radio][name=group]:checked').val();  
  const create   = checked === 'create';
  const update   = checked === 'update';
  const suppress = checked === 'suppress';
  $('#proid').toggle(!create);
  $('#deleteid').toggle(suppress);
  $('.fields').toggle(!suppress);
  $('#btnSearch').toggle(update);
}; 
$(function() {
  $('.js-example-basic-single').select2();
  // Hide show inputs
  $('input[type=radio][name=group]').on('change',checkRads);
  checkRads();
});
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" type="text/css" href="css/style.css">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-rc.2/css/materialize.min.css">
<link href="https://fonts.googleapis.com/css?family=Open+Sans&display=swap" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/select2@4.0.13/dist/css/select2.min.css" rel="stylesheet" />

<body class="body-custom">
  <div class="container">
    <div class="form">
      <div class="row">
        <form id="form" action="">
          <div class="row">
            <div class="type">
              <label>
                                <input class="with-gap" name="group" value="create" type="radio" checked />
                                <span>Create</span>
                            </label>
              <label>
                                <input class="with-gap" name="group" value="update" type="radio" />
                                <span>Update</span>
                            </label>
              <label>
                                <input class="with-gap" name="group" value="suppress" type="radio" />
                                <span>Suppress</span>
                            </label>
            </div>
          </div>
          <div id="proid" class="row">
            <div class="input-field col s11">
              <input id="profile_id" type="text" class="validate">
              <label for="profile_id">Profile ID</label>
            </div>
            <div class="input-field col s1">
              <a id="btnSearch" class="btn-floating btn-small waves-effect waves-light teal lighten-2"><i class="material-icons">search</i></a>
            </div>
          </div>
          <!-- Delete Reason -->
          <div id="deleteid" class="row">
            <div class="input-field col s12">
              <select class="js-example-basic-single" name="deletereason" id="deletereason">
                <option value="" disabled selected>Choose delete reason</option>
                <option value="1">Reason 1</option>
                <option value="2">Reason 2</option>
                <option value="3">Reason 3</option>
              </select>
            </div>
          </div>
          <div class="row fields">
            <div class="input-field col s12">
              <input id="name" name="name" type="text" class="validate">
              <label for="name">Name</label>
            </div>
          </div>
          <div class="row">
            <button class="btn waves-effect waves-light" type="submit" name="action">
                            Submit
                            <i class="material-icons right">send</i>
                        </button>
          </div>
        </form>
      </div>
    </div>
  </div>


  <script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js'></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-rc.2/js/materialize.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/select2@4.0.13/dist/js/select2.min.js"></script>
mplungjan
  • 169,008
  • 28
  • 173
  • 236
  • Hi @mplungjan - thanks for your answer, unfortunately I'm still getting the same behavior. Although it works in your code snippet, when I run it in the browser from my code, as soon as I click refresh, the Delete dropdown appears on the Create view. I should also point out that if I switch to Update view, then switch back to Create view, the delete dropdown then is NOT on the Create view any longer. But as soon as I click Refresh, it comes back. – Stpete111 Mar 09 '20 at 18:27
  • At the end of the main page function? The end of the hide/show inputs function? Or at the end of every `toggle` line? – Stpete111 Mar 09 '20 at 20:22
  • Thanks, but nope, it's still happening even after adding that. – Stpete111 Mar 09 '20 at 20:27
  • Yeah and I can't repro it in CodePen either. Let me see what else I can do here. – Stpete111 Mar 09 '20 at 20:29
  • This site isn't published yet. I'm building it locally. I can do a screenshare? Or send a video of the behavior. Just let me know, I'm flexible - I just don't have it actually published on the web yet. – Stpete111 Mar 09 '20 at 20:32
  • Ok, and actually it CAN be reproduced in the snippet above. Just run the snippet, click on Update, then right click and select Reload frame. You will then see the delete dropdown in the Create view. – Stpete111 Mar 09 '20 at 20:36