First of all, I'd like to say that this post is based on that one:
http://codeloveandboards.com/blog/2016/04/26/page-specific-javascript-in-phoenix-framework-pt-2/
But I made some changes to (IMO) simplify it...
So, let's start:
First, we can add in our file assets/js/app.js
this code:
// Import specific page views
import './views/init';
And now we'll create this init.js
file in assets/js/views/init.js
and add this code:
import loadView from './loader';
function handleDOMContentLoaded() {
const viewName = document.body.dataset.jsViewPath;
const view = loadView(viewName);
view.mount();
window.currentView = view;
}
function handleDocumentUnload() {
window.currentView.unmount();
}
window.addEventListener('DOMContentLoaded', handleDOMContentLoaded, false);
window.addEventListener('unload', handleDocumentUnload, false);
And now we'll create this loader.js
file mentioned on the import
, so create the file assets/js/views/loader.js
and add this code:
import MainView from './main';
export default function loadView(viewPath) {
if (!viewPath) return new MainView();
const ViewClass = require('./' + viewPath);
return new ViewClass.default();
}
And now this other file called main.js
in assets/js/views/main.js
with this code:
export default class MainView {
// It will be executed when the document loads...
mount() { }
// It will be executed when the document unloads...
unmount() { }
}
Nice! :)
Now in our controller, we can return a new value to the view, informing the directory of our js file, something like this:
conn
|> assign(:js_view, "posts/index")
|> render("index.html")
And now in our layout file, that may be in templates/layout/app.html.eex
we can add this code in our <body>
tag:
<body data-js-view-path="<%= assigns[:js_view] %>">
And it's ready! :)
So, we'll only try to fetch the JS file is we set the js_view
on the controller.
Now, to use it, you can create a file in assets/js/views/posts/index.js
and add code similar to this:
import MainView from '../main';
export default class View extends MainView {
mount() {
// Add your JS code here...
console.log('UHULL! It works!')
super.mount();
}
unmount() {
super.unmount();
}
}
✨
Top comments (3)
Does this mean that for each request, a JS file is generated? Or is it pre-generated with Webpack?
I don't seem to get it completely.
You will have an app.min.js file that was generated by Webpack and contains all your JS code.
But the idea of this guide is to have some kind of rule in our JS code that is similar to this:
So we'll not execute code that is not necessary for some pages...
There's also a great library that I use sometimes and do almost the same thing: github.com/lucasmazza/page.js
Oh okay ! I thought the idea was to create a JS file for each page. Makes sense now !
Thanks Ricardo !