Skip to main content

Upgrading to PMACS Frontend v2

When Migrating from PMACS Frontend v1 to v2

Before you consider upgrading to version 2.0, your app must already be running version 1.4.0 or later. Before following the guide below, make sure you follow the Upgrading to jQuery 3 guide if you haven't already!

Overview

Version 2 of the PMACS Frontend gem is a major step forward! It makes the leap from Bootstrap 4 to Bootstrap 5 and uses modern Javascript in place of jQuery and ES6 -> ES5 transpilation. As a result, PMACS Frontend has a slightly sleeker look and many more component customization options (which you can find at the Bootstrap documentation site). In addition, this release is using the latest version of StimulusJS and provides an easy way for you to start using turbo-rails if you wish!

In an effort to leave the Bootstrap 5 components as untouched as possible, no adjustments are being enforced at the gem level. We do however provide some helper CSS classes that can be applied if you wish to opt in to the pre-v2 look and feel.

With this migration to Bootstrap 5, there are certain aspects that have changed and are NOT backwards compatible without manual intervention. These will be addressed in the sections below.

Before you begin, you can run the following rake task to get you started with the upgrade. If you skip this command, each section below has a specific task that can be run:

rake pmacs_frontend:v2_upgrade

jQuery

With the current state of modern browsers, the use of jQuery really isn't necessary anymore when developing new features. Because of this, an effort has been made to eliminate all usage of jQuery within PMACS-provided libraries. Bootstrap 5 also no longer uses jQuery for any of its own components!

For the time being, jQuery is still provided by this gem for use in your projects, but at some point in the future, it may be required to add the dependency at your project level.

Sprockets ES6

The sprockets-es6 gem has finally been removed. You are now forced to rename all your .es6 files to .js files. Don't worry, there is a provided rake task you can run to make this painless if you have not already run the pmacs_frontend:v2_upgrade task!

rake pmacs_frontend:migrate_sprockets_es6

If you randomly start getting errors like NameError: uninitialized constant OpenStruct, you may need to manually import require 'ostruct'. This means you were getting these through sprockets-es6 before.

PMACS Pickers

Starting with version 2.3.0 of pmacs_pickers, a data-controller attribute is added to all pickers to enable external integration. The included PmacsPersonPickerController will automatically leverage these new attributes and take care of the initialization for you.

If your app is using this familiar snippet below for initializing a PersonPicker, you can remove it. If you are inclined to leave it as is, the code is smart enough to not double initialize your picker!

$(document).on('turbolinks:load', function() {
    PersonPicker.init('.pmacs-person-picker');
});

In case you need to manually control the initialization you can add the attribute data-auto-initialize-value="false".

Across the various PMACS projects, there is likely the use of some Bootstrap-related gems that will now also need to be upgraded. Below is a list of some of the major ones in the wild:

bootstrap_form Gem

If you are using gem 'bootstrap_form', '~> 4.5.0' in your project, you will need to unpin this to gem 'bootstrap_form' and bundle update it. Depending on if you were using wrapper_classes or not, you may not require any changes here.

bootstrap4-kaminari-views Gem

If you are using gem 'bootstrap4-kaminari-views' in your project, you will need to change this to gem 'bootstrap5-kaminari-views' and bundle update it.

<%# Bootstrap 4 %>
<%= paginate @users, theme: 'twitter-bootstrap-4' %>

<%# Bootstrap 5 %>
<%= paginate @users, theme: 'bootstrap-5' %>

Breaking Changes

Below are all the major breaking changes you will need to address in your app to make things work again. This effort may greatly vary in difficulty depending on the scope of your project.

In order to lessen the load as much as possible there is a provided rake task (and other sub-tasks) to kick-start this effort for you:

rake pmacs_frontend:kickstart_bootstrap5

Note: If you already ran the pmacs_frontend:v2_upgrade task, the above task and all tasks listed in the following subsections have been run.

Badges

Badges have made a change that requires some different CSS classes to be used.

<!-- Bootstrap 4 -->
<span class="badge-primary">Boostrap 4</span>
<span class="badge-light">Boostrap 4 Light Badge</span>

<!-- Bootstrap 5 -->
<span class="badge bg-primary">Boostrap 5</span>
<span class="badge bg-light text-dark">Boostrap 5 Light Badge</span>

Modals

Modals now require some additional classes as well as using data-bs-* attributes. They've also simplified the close button!

<!-- Bootstrap 4 -->
<div class="modal" tabindex="-1">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">Boostrap 4 modal</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>Boostrap 4 modals used to have data-* attributes and more markup required for close button!</p>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Save changes</button>
      </div>
    </div>
  </div>
</div>

<!-- Bootstrap 5 -->
<div class="modal" tabindex="-1">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">Boostrap 5 modal</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        <p>Boostrap 5 modals use data-bs-* attributes and leaner markup!</p>
      </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">Save changes</button>
      </div>
    </div>
  </div>
</div>
rake pmacs_frontend:rename_bootstrap4_data_attributes
rake pmacs_frontend:migrate_bootstrap4_modals

Tooltips

Tooltips have switched from using data-* attributes to data-bs-* attributes.

<!-- Bootstrap 4 -->
<button type="button"
        class="btn btn-secondary"
        data-toggle="tooltip"
        data-placement="top"
        title="Tooltip on top">
  Boostrap 4 tooltip!
</button>

<!-- Bootstrap 5 -->
<button type="button"
        class="btn btn-secondary"
        data-bs-toggle="tooltip"
        data-bs-placement="top"
        title="Tooltip on top">
  Boostrap 5 tooltip!
</button>

You can also add the attribute data-controller="tooltip" to automatically initialize your tooltip.

<!-- Bootstrap 5 with Tooltip stimulus controller -->
<button type="button"
        class="btn btn-secondary"
        data-bs-toggle="tooltip"
        data-bs-placement="top"
        data-controller="tooltip"
        title="Tooltip on top">
  Boostrap 5 tooltip that is auto initialized!
</button>
rake pmacs_frontend:rename_bootstrap4_data_attributes

Tabs

Tabs have switched from using data-* attributes to data-bs-* attributes

<!-- Bootstrap 4 -->
<button class="nav-link active"
        id="nav-versions-tab"
        type="button"
        role="tab"
        data-toggle="tab"
        data-target="#nav-versions"
        aria-controls="nav-versions"
        aria-selected="true">
  Bootstrap 4 Tab
</button>

<!-- Bootstrap 5 -->
<button class="nav-link active"
        id="nav-versions-tab"
        type="button"
        role="tab"
        data-bs-toggle="tab"
        data-bs-target="#nav-versions"
        aria-controls="nav-versions"
        aria-selected="true">
  Bootstrap 5 Tab
</button>
rake pmacs_frontend:rename_bootstrap4_data_attributes

Form Controls

If you are manually controlling the form-control classes for Bootstrap, you will need to make some changes. The changes are mostly surrounding select menus.

<!-- Bootstrap 4 -->
<select class="form-control">
  <option>Bootstrap 4 with form-control class</option>
</select>

<select class="custom-select">
  <option>Bootstrap 4 with custom-select class</option>
</select>

<!-- Bootstrap 5 -->
<select class="form-select">
  <option>Bootstrap 5 always uses form-select class</option>
</select>
rake pmacs_frontend:migrate_bootstrap4_form_controls

Custom File Inputs

If you are using Bootstrap 4 custom file inputs, these have sadly been removed in Bootstrap 5. They have gone to a more native approach and are delegating all behavior to whatever the browser decides. This unfortunately does leave you with uglier file inputs compared to the browser defaults.

Below is an example of a custom file input with an associated Stimulus controller. It updates the label/display when you select a file.

<!-- Bootstrap 4 -->
<div class="input-group" data-controller="file-field">
  <div class="custom-file">
    <input type="file"
           id="file-field"
           class="custom-file-input"
           title="No file selected"
           accept=".csv"
           data-file-field-target="fileField"
           data-action="change->file-field#fileSelected">
    <label class="custom-file-label" data-file-field-target="fileLabel" for="file-field">
      Custom File Input
    </label>
  </div>
</div>

<!-- Bootstrap 5 -->
<div data-controller="file-field">
  <div class="input-group">
    <input type="text"
           class="form-control custom-file-display"
           title="No file selected"
           placeholder="Custom File Input"
           readonly="readonly"
           data-file-field-target="fileInputLabel"
           data-action="click->file-field#selectFile">
    <button name="button"
            type="button"
            class="btn btn-outline-secondary"
            data-action="click->file-field#selectFile">Browse</button>
  </div>
  <input type="file"
         id="file-field"
         class="d-none"
         title="No file selected"
         accept=".csv"
         data-file-field-target="fileField"
         data-action="change->file-field#fileSelected">
</div>

Tables

Tables styled with the .table class may need some adjustments. This class now does more in Bootstrap 5 and is setting various CSS variables.

<table class="table">
  <tr>
    <td>John Smith</td>
    <td>PA</td>
  </tr>
</table>

If you want to customize the background color of your table, you can add a custom class to do so.

.table.custom-bg {
  --bs-table-bg: #f8ecd7;
  background-color: #f8ecd7;
}
<table class="table custom-bg">
  <tr>
    <td>colored table</td>
    <td>I am pretty</td>
  </tr>
</table>
rake pmacs_frontend:migrate_bootstrap4_light_striped_tables

CSS Variables

Bootstrap 5 uses CSS variables much more extensively compared to Bootstrap 4. This allows for more runtime styling options as opposed to fully SASS which is at compile time.

If your project level CSS uses any type of variables, you will most likely need to prefix them with bs-.

/* Bootstrap 4 */
.text-green {
  color: var(--success);
}

/* Bootstrap */
.text-green {
  color: var(--bs-success);
}

Visual Changes

With a major upgrade to any frontend framework, there are going to be some UI modifications. In most cases, they're an improvement upon the existing components. In others, you may want to retain the styling from the previous version. The following sections describe a few instances where this may apply.

By default, all links in Bootstrap 5 are underlined. If you would like them to remain without text-decoration, like in Bootstrap 4, you can add a no-underline-link class to your links.

PMACS Frontend itself is using these classes for the default layout.

<a class="no-underline-link" href="https://ilovebootstrap5.com">
  I now look like Bootstrap 4 and also have no underlines.
</a>

<%= link_to(name, user_path(user), class: 'no-underline-link') %>
<%= mail_to(val, class: 'no-underline-link') %>

<button type="button" class="btn btn-link no-underline-link">I am a button link without being underlined</button>

<div class="no-underline-links">
  <a href="https://ilovebootstrap5.com">
    I now look like Bootstrap 4 and have no underlines. I can thank my parent!
  </a>
  <a href="https://ilovebootstrap5.com">
    I now look like Bootstrap 4 and also have no underlines. I can also thank my parent for the class!
  </a>
</div>

To globally remove the link underlines you can add something like this to your CSS/SCSS:

:root {
  --bs-link-decoration: none;
}

a {
  text-decoration: none;

  &:hover {
    text-decoration: underline;
  }
}

Striped Tables

In previous versions of PMACS Frontend we were overriding the default color provided by the Bootstrap table-striped class.

Going forward, the default behavior is brought in from Bootstrap 5. You can add the table-striped-light class to achieve the same look as the striped tables from pre-v2.

<table class="table table-striped">
  <tr>
    <td>John Smith</td>
    <td>PA</td>
  </tr>
</table>

<!-- Bootstrap 5 -->
<table class="table table-striped table-striped-light">
  <tr>
    <td>John Smith</td>
    <td>PA</td>
  </tr>
</table>

Fieldsets

By default, all fieldset legends are now set to float: left. This may mess up your UI if you are relying on it looking like a typical fieldset. You can add a no-float-legend class to the fieldset itself to make this look good again.

<fieldset class="no-float-legend">
  <legend>I look like Bootstrap 4 again</legend>
</fieldset>

Example Converted Projects

Before you begin the process of upgrading, it may be useful to see a few examples of projects that have already been converted.

There are endless scenarios in the wild, so your level of effort may vary greatly!