This is based on Gazler's comment on the question and is a slightly more general answer than the one submitted by cmititiuc. You don't strictly need to wrap your page-specific JavaScript code like in that answer, nor do anything beyond import your page-specific file in the page-specific script
element.
Layout templates
Use Phoenix.View.render_existing/3
in your layouts like this:
<head>
<%= render_existing @view_module, "scripts.html", assigns %>
</head>
... or this:
<head>
<%= render_existing @view_module, "scripts." <> @view_template, assigns %>
</head>
For the first example, this will render a "scripts.html"
template if one exists for the relevant view module.
For the second example, a "scripts." <> @view_template
template, e.g. scripts.form.html, will be rendered if it exists.
If the 'scripts' template does NOT exist for a view module, nothing will be output in the page HTML.
View modules
For the first example using render_existing/3
in the layout template, you'd add code like this to the post view module:
def render("scripts.html", _assigns) do
~E(<script src="file.js"></script>)
end
... and for the second you'd add code like this:
def render("scripts.show.html", _assigns) do
~E(<script src="show-file.js"></script>)
end
def render("scripts.index.html", _assigns) do
~E(<script src="index-file.js"></script>)
end
Details
The difference between render_existing
and render
is that the former won't raise an error if the referenced template does NOT exist (and nothing will be output in the page HTML in that case either).
The ~E
sigil provides "HTML safe EEx syntax inside source files" and is similar to (in most cases, or maybe even always) the corresponding code from cmititiuc's answer:
~s{<script>require("web/static/js/posts").Post.run()</script>}
|> raw
Conclusion
In general then, for any page for which you want to import specific JavaScript files via script
elements in the page head
(or at the end of the body
), or link CSS files, or do anything to the page output in a portion thereof otherwise handled by the layout, you'd use render_existing
in the layout template as above and then implement appropriate render
clauses in the view modules for those pages.
And further, there's no reason why you couldn't use something like both of the two examples above so that, for any view module and its templates, you could both:
- Include some script(s) (or CSS files or otherwise manipulate the HTML output of in a layout template) for all the view module templates (but not all templates for the entire app)
- Include some script(s) (or ...) for only a single template