Phoenix 1.5 include materialize-css using npm

Hi, I’m new to Phoenix. I’m using 1.5 to build a web application. I want to use materializecss.
I know I can directly copy the cdn urls and paste it to layout file. But I want to do it via npm.
So, I found this package materialize-css and installed it inside the assets folder using npm install materialize-css@next --save.

The problem I’m facing is, I included @import "~materialize-css/dist/css/materialize.min.css"; in my app.scss file. Also, added import "materialize-css/dist/js/materialize.min"; in my app.js file.

When I run mix phx.server it’s giving me error

ERROR in multi ./js/materialize.min.js
Module not found: Error: Can’t resolve ‘./js/materialize.min.js’ in ‘/Users/imtiaz/Etectra/work/recyclebin/assets’
@ multi ./js/materialize.min.js materialize[0]

Any idea how to resolve it?

Hello and welcome,

Try to change this to…

import "../node_modules/materialize-css/dist/js/materialize.min";
2 Likes

Thanks @kokolegorille. It doesn’t solve the problem. I guess it’s showing this because inside my webpack.config.js there is a line:

entry: {
      'app': glob.sync('./vendor/**/*.js').concat(['./js/app.js']),
      'materialize': glob.sync('./vendor/**/*.js').concat(['./js/materialize.min.js'])
    },

I removed the line with materialize and it removes the error. Not sure why I’m getting jquery is undefined.

I installed jquery via npm and added

new webpack.ProvidePlugin({
        $: "jquery",
        jQuery: "jquery"
      })

inside webpack.config.js file’s plugin section.

Also, in app.js added:

import $ from 'jquery';
window.jQuery = $;
window.$ = $;

Any idea? I know it’s a question inside another question, but I’m a newbie and getting issues every time :frowning:

It’s something I had to do for BS4, luckily now BS5 dropped jquery.

I try not to include jquery. JS has evolved enough not to need it anymore.

But when needed, I found some different solutions, one is to use splitChunks.

module.exports = (_env, options) => {
    optimization: {
      splitChunks: {
        cacheGroups: {
          vendor: {
            test: /bootstrap|jquery|popper.js/,
            chunks: "initial",
            name: "vendor",
            enforce: true
          }
        }
      },
      minimizer: [
        new TerserPlugin({}),
        new CssMinimizerPlugin({})
      ]
    },
      ...
      plugins: [
        ...
        new webpack.ProvidePlugin({ // inject ES5 modules as global vars
          $: "jquery",
          jquery: "jquery", "window.jQuery": "jQuery",
          Popper: ["popper.js", "default"],
        })
      ]
}

Nothing special in app.js (remove your code)

And modify layout like this.

    <script type="text/javascript" src="<%= Routes.static_path(@conn, "/js/vendor.js") %>"></script>
    <script type="text/javascript" src="<%= Routes.static_path(@conn, "/js/app.js") %>"></script>

The example is for bootstrap 4, so You can remove popper too.

Now I try to avoid css framework with jquery dependency.

Needless to say it’s a real pain :slight_smile:

Seems like a real pain adding jquery. Now, everything fall apart. materialize.min.js giving errors that jQuery is not defined :disappointed:

I guess, need to find a css framework without jquery dependency

I tried materialize-css some years ago, but now I would try

or the lite version.

Hi guys,

I can not figure out a working solution for Phoenix 1.5 (incl. Liveviews) + materializecss.
Webpack Version is 4.41.5.

A working result should achieve the following working:
Side-Nav-Materializecss

So that I can call:
$(".button-collapse").sideNav();

at the bottom of template or via liveview-hooks.

In my tries to get a solution (alot of hours by now), I also face the “jquery ($ not found)” problem.

Is there someone out with a working solution?

Thanks so much for the help!

How do You load jQuery?

It might not be available yet and You might need to use something like…

document.addEventListener("DOMContentLoaded", function(){
  // Code
}

I tried a modification in the default generated ‘app.js’ in previous tries:

window.addEventListener(“phx:page-loading-start”, info =>
{
topbar.show()
$(".button-collapse").sideNav()
})

Current state of Chrome-Console:

Uncaught TypeError: Cannot read property ‘scrollHeight’ of null
at rc2Contentscript.js:249
(anonymous) @ rc2Contentscript.js:249
setInterval (async)
listenToParent @ rc2Contentscript.js:246
(anonymous) @ rc2Contentscript.js:626
localhost/:10

GET http://localhost:4005/js/vendor.js net::ERR_ABORTED 404 (Not Found)

app.js?7473:37 Uncaught TypeError: $(…).sideNav is not a function
at eval (app.js?7473:37)
at Object.dispatchEvent (phoenix_live_view.js?0c87:1)
at e.value (phoenix_live_view.js?0c87:1)
at e.value (phoenix_live_view.js?0c87:1)
at e.value (phoenix_live_view.js?0c87:1)
at eval (phoenix_live_view.js?0c87:1)
at Array.forEach ()
at Object.all (phoenix_live_view.js?0c87:1)
at e.value (phoenix_live_view.js?0c87:1)
at t (phoenix_live_view.js?0c87:1)

What happens when You type $ in devtools console?

What is this rc2Contentscript.js?

What happens when You type $ in devtools console?

$

Returns:

ƒ $() { [native code] }

What is this rc2Contentscript.js?
Good question, I guess its coming from webpack. It is not from my code:
After searching the web I found following regarding nextcloud:

https://github.com/nextcloud/forms/issues/842

My webpack-Config looks like that:

const path = require(‘path’);

const glob = require(‘glob’);

const HardSourceWebpackPlugin = require(‘hard-source-webpack-plugin’);

const MiniCssExtractPlugin = require(‘mini-css-extract-plugin’);

const TerserPlugin = require(‘terser-webpack-plugin’);

const OptimizeCSSAssetsPlugin = require(‘optimize-css-assets-webpack-plugin’);

const CopyWebpackPlugin = require(‘copy-webpack-plugin’);

const webpack = require(‘webpack’);

module.exports = (env, options) => {

const devMode = options.mode !== ‘production’;

return {

optimization: {

  minimizer: [

    new TerserPlugin({ cache: true, parallel: true, sourceMap: devMode }),

    new OptimizeCSSAssetsPlugin({})

  ]

},

entry: {

  'app': glob.sync('./vendor/**/*.js').concat(['./js/app.js'])

},

output: {

  filename: '[name].js',

  path: path.resolve(__dirname, '../priv/static/js'),

  publicPath: '/js/'

},

devtool: devMode ? 'eval-cheap-module-source-map' : undefined,

module: {

  rules: [

    {

      test: /\.js$/,

      exclude: /node_modules/,

      use: {

        loader: 'babel-loader'

      }

    },

    {

      test: /\.[s]?css$/,

      use: [

        MiniCssExtractPlugin.loader,

        'css-loader',

        'sass-loader',

      ],

    },

    {

      test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,

      use: [{

        loader: 'file-loader',

        options: {

          name: '[name].[ext]',

          outputPath: '../fonts'

        }

      }]

    }

  ]

},

plugins: [

  new MiniCssExtractPlugin({ filename: '../css/app.css' }),

  new CopyWebpackPlugin([{ from: 'static/', to: '../' }]),

  new webpack.ProvidePlugin({ // inject ES5 modules as global vars

    $: "jquery",

    jquery: "jquery", "window.jQuery": "jQuery"

  }),

  new webpack.LoaderOptionsPlugin({                                   

    // test: /\.xxx$/, // may apply this only for some modules        

    options: {

      splitChunks: {

        cacheGroups: {

          vendor: {

            test: /jquery.js/,

            chunks: "initial",

            name: "vendor",

            enforce: true

          }

        }

      }                  

    }                                                                 

  })                                                                  

]

.concat(devMode ? [new HardSourceWebpackPlugin()] : [])

}

};

I don’t remember WP 4 config.

A lot have changed since WP 5 and some tools are now obsolete.

Like CopyWebpackPlugin, HardSourceWebpackPlugin and Terser config.

I cannot help You on this, Webpack is such an annoying tool to configure.

Thanks anyway for trying!

Maybe someone else figured it out and can post a working sample code.