Search code examples
javascripthtmlbootstrap-5razor-pages

How to Automatically Scroll to Bottom of Modal Content in Bootstrap 5 on a Razor Page


I'm working on a web application using Razor Pages and Bootstrap 5 modals to display dynamic content. I need the content inside the modal to automatically scroll to the bottom when the modal is opened or when content is dynamically added. However, my attempts to achieve this have not been successful. Here's the structure of my modal and the JavaScript code I've been using.

Modal HTML Structure in Razor Page:

<!-- Modal for Comments -->
<div class="modal fade" id="commentsModal" tabindex="-1" aria-labelledby="commentsModalLabel" aria-hidden="true">
    <div class="modal-dialog modal-lg">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="commentsModalLabel">Comments</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
            </div>
            <div class="modal-body">
                <div class="scrollable-content" style="height: 300px; overflow-y: auto;">
                    <div id="message-container">
                        <!-- Dynamic messages will be loaded here -->
                    </div>
                </div>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
                <button type="button" class="btn btn-primary" id="addComment">Add Comment</button>
            </div>
        </div>
    </div>
</div>

JavaScript Code:

$(document).ready(function () {
    function scrollToBottom() {
        var scrollableContent = $('.scrollable-content');
        scrollableContent.each(function () {
            $(this).scrollTop($(this)[0].scrollHeight);
        });
    }

    $('#commentsModal').on('shown.bs.modal', function () {
        setTimeout(scrollToBottom, 100); // Add a slight delay to ensure content is fully loaded
    });

    $('a[data-bs-toggle="tab"]').on('shown.bs.tab', function () {
        setTimeout(scrollToBottom, 100); // Add a slight delay to ensure content is fully loaded
    });

    $('#addComment').on('click', function() {
        // Simulate adding a comment dynamically
        $('#message-container').append('<div class="comment">New comment</div>');
        scrollToBottom();
    });
});

Problem: The content inside the modal doesn't scroll to the bottom automatically when the modal is opened or when new content is dynamically added. I've tried adding a delay using setTimeout, but it doesn't seem to work consistently.

What I've Tried:

Adding a delay to ensure content is fully loaded. Triggering the scroll function on shown.bs.modal and shown.bs.tab events. What I'm Looking For: I need a reliable way to automatically scroll to the bottom of the modal content when the modal is opened and when new content is dynamically added. Any advice or solutions would be greatly appreciated.

Additional Information:

Using Razor Pages Bootstrap version: 5.1 jQuery version: 3.6.0 Aspnet razor pages .net 8


Solution

  • I set this up as a snippet that when run shows the modal then after 5 seconds adds content, then 1 second later scrolls to the bottom - seems to be working for me.

    $(function() {
      function scrollToBottom() {
        const scrollableContent = $('.scrollable-content');
        scrollableContent.scrollTop(scrollableContent[0].scrollHeight);
      }
    
      $('#addComment').on('click', function() {
        $('#message-container').append('<div class="comment d-flex align-items-end">New comment</div>');
        setTimeout(scrollToBottom, 1000);
      });
      $("#commentsModal").on('shown.bs.modal', function(event) {
        setTimeout(function() {
          $('#addComment').trigger('click')
        }, 5000);
      });
    
      setTimeout(function() {
        $(' .launch-modal').trigger('click')
      }, 6000);
    });
    body {
      display: grid;
      place-items: center;
      height: 100vh;
    }
    
    .comment {
      background-color: #00ffa940;
      height: 40em;
    }
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    
    <div class="modal fade" id="commentsModal" tabindex="-1" aria-labelledby="commentsModalLabel" aria-hidden="true">
      <div class="modal-dialog modal-lg">
        <div class="modal-content">
          <div class="modal-header">
            <h5 class="modal-title" id="commentsModalLabel">Comments</h5>
            <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
          </div>
          <div class="modal-body">
            <div class="scrollable-content" style="height: 300px; overflow-y: auto;">
              <div id="message-container">
                <!-- Dynamic messages will be loaded here -->
              </div>
            </div>
          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
            <button type="button" class="btn btn-primary" id="addComment">Add Comment</button>
          </div>
        </div>
      </div>
    </div>
    <button type="button" class="btn btn-primary launch-modal" data-bs-toggle="modal" data-bs-target="#commentsModal">
      Launch comment modal (will auto click in 6 seconds)
    </button>