Bootstrap has a nice Toast implementation but it expects the toast HTML structure to be built and then lets you manage that via JavaScript. BUT, what if you want something a little more flexible and sophisticated? Maybe the notifications will sometimes come several at a time and you'd like to stack them.
Bootstrap has a solution for that too - but again, it expects the HTML structure of multiple toast sections to be built and in place.
What I really wanted was to be able to dynamically create the toast structure, insert it into the DOM and, if applicable, have them stack nicely rather than overlap.
Here's what I ended up with, and it works pretty nicely.
The HTML for the Toast Container looks like this:
<!--toast messaging-->
<div class="toast-container" id="toastContainer"></div>
The Javascript
popToast: function (bodyText) {
//when we pop a toast notification
//we are dynamically creating the toast element and adding it to the default.html toastContainer
//we also try to figure out how to stack them b/c bootstrap doesn't do that - even if placed in a toast-container div
//get the container and count/calculate the bottom placement of the toast about to be added
var container = document.getElementById("toastContainer");
var containerCount = container.childElementCount;
var noticePlacement = containerCount === 0 ? "5px" : (containerCount * 105) + "px";
//the static template
var toastTemplate = `<div style="z-index: 9999;width:400px;${noticePlacement};position:fixed;margin-left:40%;margin-right:40%" class="toast" role="alert" aria-live="assertive" data-bs-delay="4000" aria-atomic="true">
<div class="toast-header" style="background-color:skyblue">
<strong class="me-auto" style="color:white">iQueue</strong>
<small style="color:white">moments ago</small>
<button type="button" class="btn-close" data-bs-dismiss="toast" style="color:white" aria-label="Close"></button>
</div>
<div class="toast-body" id="divMainToast">
${bodyText}
</div>
</div>`;
//create the template and toast elements/add to container
var newToastTemplate = document.createElement("template");
newToastTemplate.innerHTML = toastTemplate.trim();
var newToast = newToastTemplate.content.firstChild;
document.getElementById("toastContainer").appendChild(newToast);
//create/show the bs toast object from the dynamically created toast element
var bsToast = new bootstrap.Toast(newToast);
bsToast.show();
//remove this toast element from the container when it fires the hidden event
newToast.addEventListener("hidden.bs.toast", function () {
document.getElementById("toastContainer").removeChild(newToast);
})
},
Notes
In a nutshell, when popToast() is called, it adds a bootstrap toast structure to the container. The toastTemplate string pulls in the values for the body of the toast and the placement needed to stack. Placement is a calculation based on the number of existing notifications - to get a stacked effect.
I did a little playing with the standard format of the toast (made it wider, used my own color scheme, etc).
It's important to remember to remove the toast from the container when its "hidden" event is fired - that's what the addEventListener() does at the end. This keeps the container child count accurate.
There are probably much better ways to accomplish this - but this approach does what i need it to do with little extraneous coding required.
No comments:
Post a Comment