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.