Search code examples
javascripthtmlmodal-dialogbootstrap-modal

Modal screen doesn't render properly when screen scrolled


I have a screen that pops up a modal when the user clicks on a table button to edit the role of a specific user. The users are displayed in a table that renders such that it overflows the screen and you have to scroll to see the users toward the bottom of the list. When the screen is at the top of the scroll, the modal renders correctly.

Proper rendering of the modal

But when I scroll down further into the table, the screen renders with the top of the modal cut off and the grayed out area not extending to the bottom of the page.

Truncated modal on screen scroll

What I need is to have the modal fill the visible screen, not from the top down as it is currently doing. Any help you can provide will be greatly appreciated.

Here is the HTML/JavaScript code that renders the modal.

<!-- Modal for User Role Update -->
<div class="modal fade modal-center" id="updateUserRole" tabIndex="-1" role="dialog" aria-labelledby="updateUserRoleModalLabel" aria-hidden="true" data-backdrop="false">
    <form id="updateUserRoleModalForm" method="post">
        <div class="modal-dialog modal-lg" role="document">
            <div class="modal-content modal-content-role">

                <div class="modal-header p-3 bg-primary">
                    <h5 class="modal-title pl-3" id="updateUserRoleLabel">Edit User Role</h5>
                        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                            <span aria-hidden="true">&times;</span>
                        </button>
                </div>

                <div class="modal-body p-4">
                    <div class="div-registration px-3">
                        <div class="div-update-form-input">

                            <div class="form-group d-flex flex-row align-items-center mb-2 text-secondary">
                                <div class="form-label">
                                    <label type="label" name="lblUserID" data-toggle="tooltip" data-placement="left" title="Selected user">User ID</label>
                                    <i class="px-1 fa fa-user text-secondary larger-icon" aria-hidden="true"></i>
                                </div>
                                <div class="form-input">
                                    <input type="text" class="form-control disabled-input ml-2 currentUserId" id="userID" name="userID"
                     style="background-color: lightgray;" <%- user_name_cd %> placeholder="USER ID" disabled>
                                </div>
                            </div>
                            <div class="form-group d-flex flex-row align-items-center mb-2 text-secondary">
                                <div class="form-label">
                                    <label type="label" name="lblCurrentRoleCode" data-toggle="tooltip" data-placement="left" title="Current role code">Current Role</label>
                                    <i class="px-1 fa fa-user-times text-secondary larger-icon" aria-hidden="true"></i>
                                </div>
                                <div class="form-input">
                                    <input type="text" class="form-control disabled-input ml-2 currentRoleCode" id="currentRoleCode" name="currentRole"
                     style="background-color: lightgray;" <%- user_name_cd %> placeholder="CURRENT ROLE CODE" disabled>
                                </div>
                            </div>
                            <div class="form-group d-flex flex-row align-items-center mb-2 text-secondary">
                                <div class="form-label">
                                    <label type="label" name="lblNewRoleCode" data-toggle="tooltip" data-placement="left" title="New role code">Assign New Role</label>
                                    <i class="px-1 fa fa-user-plus text-secondary larger-icon" aria-hidden="true"></i>
                                </div>
                                <div class="form-input">
                                    <select class="form-control ml-2 form-select form-select-lg" aria-label="Default option is Standard User"
                      id="newRoleCode" name="newRole" style="background-color: palegoldenrod; font-weight: bold;">
                                    </select>
                                </div>
                            </div>

                         </div>
                     </div>
                 </div>

                 <div class="modal-footer px-3 pb-3">
                     <button type="button" id="updateUserRoleCancelBtn" class="btn btn-secondary rounded py-2 px-3 modal-button" data-dismiss="modal">Close</button>
                     <button type="submit" id="updateUserRoleSaveBtn" class="btn btn-primary rounded py-2 px-3 modal-button" value="" name="user_id" formaction="/usr/updateuserrole">Save</button>
                 </div>

             </div>
          </div>
      </form>
  </div>

  <script src="/javascripts/jquery.min.js"></script>
  <script src="/javascripts/bootstrap.min.js"></script>
  <script src="/javascripts/bootstrap-toggle.min.js"></script>

  <script>
    // Change user role in modal
  $('#updateUserRole').on('show.bs.modal', function(event) {
      var button = $(event.relatedTarget);
      var userId = button.data('userid');
      var currentRoleCode = button.data('currentrolecode');
      var roles = ['R', 'M', 'A'];

      var modal = $(this);
      modal.find(".currentUserId").val(userId);
      document.getElementById("updateUserRoleSaveBtn").value = userId;

      var roleName = getRoleName(currentRoleCode);
      modal.find(".currentRoleCode").val(roleName);

      var roleSelect = document.getElementById('newRoleCode');

      // Clear the <select> list so every visit doesn't append duplicate role codes
      if (roleSelect.length > 0) {
          for (var j = roleSelect.length - 1; j >= 0; j--) {
              roleSelect[j].remove();
          }
      }

      // Create the <option> entries for roles in the modal
      for (var i = 0; i < roles.length; i++) {
          var role = getRoleName(roles[i]);
          var opt = document.createElement('option');
          opt.innerHTML = role;
          opt.value = role;
          roleSelect.appendChild(opt);

          // Don't show role if user already that particular role
          if (currentRoleCode == roles[i]) {
              roleSelect[i].remove();
          }
      }
  });

Solution

  • I came up with a solution. It's kinda klugy. I added the following line to the top of the script where the modal is populated:

    document.body.style.overflow = 'visible';
    

    Now the screen automatically scrolls to the top when invoked. The "klugy" part is that now a user can scroll the table, but this is minor compared to having the modal cut off. Additionally, the solution is only 100% effective with the Chrome and Edge browsers. Firefox still renders the cut-off version of the modal when the table is near but not at the top; however, because the screen now scrolls, this is a minor inconvenience as opposed to a genuine problem.