Mastodon hachyterm.io

I’m currently working through Mastering Phoenix Framework by Shankar Dhanasekrann.

The book teaches you how to build a shop application with Test-Driven Development using Phoenix.
But the code uses Phoenix 1.3.

Phoenix 1.3 still uses brunch for JavaScript asset generation. And the framework ships with Bootstrap for CSS.
In v1.4 the authors replaced brunch with webpack. And now Phoenix uses Milligram, a minimalist CSS framework, instead of the heavyweight Bootstrap.

But what if you want to use Bootstrap, SASS, jquery and jquery plugins like Bootstrap Notify?

Abdulhakim Haliru wrote a good blog post on how to install Bootstrap, etc..
If you also want to use jquery plugins and SASS some additional steps are necessary.

Install NPM Plugins

Navigate to your Phoenix project and find the assets folder.

$ cd assets
$ npm install --save font-awesome bootstrap bootstrap4-notify jquery
$ npm install --save-dev file-loader sass-loader@7.3.1 node-sass

Bootstrap4-notify adds “growl-like” notifications to your web page. They are a nicer looking alternative to pop-ups.

I had problems with the latest version of sass-loader but version 7.3.1 works.

If you don’t want to use bootstrap4-notify, you can use popper.js for Bootstrap’s “native” pop-ups:

$ cd assets
$ npm install --save font-awesome bootstrap popper.js jquery
$ npm install --save-dev file-loader sass-loader@7.3.1 node-sass

Webpack Configuration

Add this to your webpack.config.js in your assets folder:

// at the top of the file where your import statements are
//...
const webpack = require('webpack')

// inside the `module.exports` object
module.exports = (env, options) => ({
  // ....
  module: {
    rules: [
      {
        test: /\.(scss)$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'], // needed for SCSS
      },
      {
        test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/, // needed for font-awesome
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '[name].[ext]',
              outputPath: '../fonts',
            },
          },
        ],
      },
    ],
  },
  plugins: [
    new webpack.ProvidePlugin({
      // add jquery
      $: 'jquery',
      jQuery: 'jquery',
    }),
  ],
})

You need file-loader for Font Awesome, and webpack.ProvidePlugin to add jquery support.

Here is a link to my webpack.config.js.

Add Bootstrap and Font Awesome to CSS

Create the app.scss file under assets/css (delete app.css):

$fa-font-path: '~font-awesome/fonts';
@import '~bootstrap/scss/bootstrap.scss';
@import '~font-awesome/scss/font-awesome.scss';

/* Phoenix flash messages */
.alert:empty {
  display: none;
}

/* Phoenix inline forms in links and buttons */
form.link,
form.button {
  display: inline;
}

Read more about how to use Font Awesome with Sass/SCSS on the official website.

Add jquery and jquery Plugins to JavaScript

Here is an example for using Bootstrap Notify when you add an item to a cart.
Make note of the imports at the top of the file.

The file is app.js under assets/js:

import 'bootstrap'
import 'bootstrap4-notify'
import $ from 'jquery'
import css from '../css/app.scss'
import '../../deps/phoenix_html'

window.jQuery = $
window.$ = $

function ajaxHandler(e) {
  e.preventDefault()
  var post_url = $(this).attr('action') //get form action url
  var form_data = $(this).serialize() //Encode form elements for submission

  $.post(post_url, form_data, function(response) {
    // use $.notify for Bootstrap-Notify
    $.notify({
      message: response.message,
      offset: 60,
      type: 'success',
    })
    $('.cart-count').text(response.cart_count)
  })
}

var ajaxCart = {
  init: function() {
    $(function() {
      $('.cart-form').on('submit', ajaxHandler)
    })
  },
}

// init ajax
ajaxCart.init()

Further Reading