'How can I display custom messages to the user via modals?

When I try to implement user messages in modals, I encounter bugs.

function foo(title, description) {
  var myModalErrorMessage;
  $("#customErrorMessageTitle").text(title)
  $("#customErrorMessageDescription").html(description)
  myModalErrorMessage = new bootstrap.Modal(document.getElementById("customErrorMessage"), {});
  myModalErrorMessage.show();

}

foo("my title 1", "my description 1")
foo("my title 2", "my description 2")
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.6.0.slim.min.js" integrity="sha256-u7e5khyithlIdTpu22PHhENmPcRdFiHRjhAuHcs05RI=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>

<div class="modal" id="customErrorMessage" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title" id="customErrorMessageTitle" style="color:red; font-weight:bold"></h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body" id="customErrorMessageDescription" style="color:red;">
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">close</button>
      </div>
    </div>
  </div>
</div>

also after I close the modal, the faded background is remained.

X messages should be displayed to the user (depends how many times I call my foo function and pass it title and description).

Thanks.



Solution 1:[1]

This happening because you are opening modal multiple times on same view, that's why the background is created multiples times on the view, but when you close the view it only hides the first one. you can use $('.modal-backdrop').remove(); code to hide all active backgrounds. If you want to open multiple modals on same page you can view Demo here

function foo(title, description) {
  var myModalErrorMessage;
  $("#customErrorMessageTitle").text(title)
  $("#customErrorMessageDescription").html(description)
  myModalErrorMessage = new bootstrap.Modal(document.getElementById("customErrorMessage"), {});
  myModalErrorMessage.show();

}
function closeModal(){
$("#customErrorMessage").modal('hide');
$('.modal-backdrop').remove();
}
foo("my title 1", "my description 1")
foo("my title 2", "my description 2")
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.6.0.slim.min.js" integrity="sha256-u7e5khyithlIdTpu22PHhENmPcRdFiHRjhAuHcs05RI=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>

<div class="modal" id="customErrorMessage" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title" id="customErrorMessageTitle" style="color:red; font-weight:bold"></h5>
        <button type="button" class="btn-close" onclick="closeModal()" aria-label="Close"></button>
      </div>
      <div class="modal-body" id="customErrorMessageDescription" style="color:red;">
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" onclick="closeModal()">close</button>
      </div>
    </div>
  </div>
</div>

Solution 2:[2]

You can use <template> to render your custom Modal windows. For more details, take a look on Code Snippet comments.

Your problem is you calling same instance twice (like in example), so you override text content of modal to text from latest call, and when opening modal with modal.show(), BS5 generates div.modal-backdrop to each modal. So, you have one modal window with two backdrops and when closing window, you closing this one instance and BS5 removing related backdrop. The other backdrop will stay.

You have to generate separate modal windows, for example, with template tag.

Also, BS5 works without jQuery, so no needs to use it here.

const foo = (title, description) => {
  // root anchor to place modals
  const body = document.querySelector('body');
  // template with HTML to render
  const template = document.querySelector('#modalTemplate');

  // prepare clone to render content
  const clone = template.content.cloneNode(true);

  // searching for main tags to work with
  const modalNode = clone.querySelector('.modal');
  const titleNode = clone.querySelector('.modal-title');
  const textNode = clone.querySelector('.modal-body');

  // create modal id and label
  const timestamp = + new Date();
  // const modalId = `modal-${timestamp}`; // id is optional
  const modalLabel = `modal-label-${timestamp}`;
  
  // placing content into tags
  // modalNode.id = modalId; // id is optional
  modalNode.setAttribute('aria-labelledby', modalLabel);
  
  titleNode.id = modalLabel;
  titleNode.textContent = title;
  
  // insert text into body
  textNode.textContent = description;
  
  // create BS modal
  modal = new bootstrap.Modal(modalNode, {});

  // show modal
  modal.show();
  
  // rendering modal in DOM
  body.appendChild(clone);
}

// call functions to render custom modal
foo("my title 1", "my description 1");
foo("my title 2", "my description 2");
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>

<!-- main template block -->
<template id="modalTemplate">
  <!-- id and label for .modal will be added by JS -->
  <div class="modal" tabindex="-1" aria-hidden="true">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
          <!-- id and text content for .modal-title will be added by JS -->
          <h5 class="modal-title text-danger fw-bold"></h5>
          <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
        </div>
        <!-- text content for .modal-body will be added by JS -->
        <div class="modal-body text-danger"></div>
        <div class="modal-footer">
          <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">close</button>
        </div>
      </div>
    </div>
  </div>
</template>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2