bootstrap.native: How to Use Toast Component

kinopyo avatar

kinopyo

In my previous post, I covered how to use bootstrap.native so you can drop the jQuery dependency right now. In this post, I'm gonna share how to use Toast component with bootstrap.native.

Toast UI

Toast component in Bootstrap
Toast component in Bootstrap

This popular UI component was added in Bootstrap 4.2. So first make sure you upgrade to 4.2+ to get the CSS.

I'm using bootstrap gem in my Rails app. Update the version and run bundle to install.

gem "bootstrap", "~> 4.2.1"

Then import the component's css.

@import "bootstrap/modal";
+@import "bootstrap/toasts";
@import "bootstrap/tooltip";

Add "toast" to bootstrap.native loader:

environment.loaders.append("bootstrap.native", {
  test: /bootstrap\.native/,
  use: {
    loader: "bootstrap.native-loader",
    options: {
-     only: ["alert", "button", "dropdown", "modal", "tab", "tooltip"],
+     only: ["alert", "button", "dropdown", "modal", "tab", "toast", "tooltip"],
      bsVersion: 4
    }
  }
})

That's all the setup.

How to use

A slim-down version of the markup from the official doc:

<div class="toast">
  <div class="toast-header">
    <strong>Bootstrap</strong>

    <button type="button" class="close" data-dismiss="toast">
      <span aria-hidden="true">&times;</span>
    </button>
  </div>
  
  <div class="toast-body">
    This is a toast message.
  </div>
</div>

Initialize it from JavaScript like this:

import "bootstrap.native"

const toast = document.querySelector("[data-dismiss=toast]")
toast["Toast"].show()

That should display the toast and it'll disappear in a few seconds.

Breakdown

As the official doc says, "Toasts are opt-in for performance reasons, so you must initialize them yourself."

To do so in bootstrap.native, we first get the element by querying [data-dismiss=toast].
Then, we access the instance with toast["Toast"] which can perform all the methods such as .show(), .hide(), and .dispose().

That is the syntax of accessing the component instance in bootstrap.native - element[string name of the component]. It's much easier to take a look at the implementation of Toast and see how it stores the instance.

Integrate with Rails Flash

ActionDispatch Flash is a common way of setting notices or alerts after certain actions in the controller.

redirect_to post, notice: "Post successfully created!"
redirect_to login_path, alert: "You must be logged in"

So far I've been using Bootstrap Alerts component to display the flash message. This time, I want to migrate it to the Toast component.

<% flash.each do |type, message| %>
  <% next unless %w[alert notice].include?(type) %>

  <div class="toast toast--<%= type %>" role="alert" aria-live="assertive" aria-atomic="true">
    <div class="toast-body">
      <span class="mr-auto"><%= message %></span>
      
      <button type="button" class="ml-2 mb-1 close" data-dismiss="toast" aria-label="Close" data-delay="3000">
        <span aria-hidden="true">&times;</span>
      </button>
    </div>
  </div>
<% end %>

First, in a partial erb, we filter flash enumerable and find :alert or :notice type of messages.Then we can use the type as part of the css to style them differently. We can also specify data-delay="3000" so the Toast message automatically disappears in 3 seconds.

Go back to our JavaScript and add a presence check. There is only one Toast message at a screen for now.

import "bootstrap.native"

document.addEventListener("turbolinks:load", () => {
  BSN.initCallback(document.body)

  const toast = document.querySelector("[data-dismiss=toast]")
  if (toast) {
    toast["Toast"].show()
  }
})

Finally, render the partial in the main layout file.

<body>
  <%= render "layouts/toast_message" %>
  <%= yield %>
</body>

I'll leave the css up to you 😉 .

That's it. Now you can use Flash alert and message just like before and they'll be displayed in the Toast component transparently.

Hope you find it useful. Thanks for reading.

kinopyo avatar
Written By

kinopyo

Indoor enthusiast, web developer, and former hardcore RTS gamer. #parenting
Published in Rails
Enjoyed the post?

Clap to support the author, help others find it, and make your opinion count.