I'm currently experimenting with the Elixir Phoenix framework together with Liveview. For my project, I would like to write some Javascript code that is only imported on certain pages (templates). Although this seems like something very trivial, I am struggling to get it working.
At this moment I created a seperate Javascript file as such assets/js/custom.js
. After doing this, I added the following line to my root.html.heex as a first test to see if this already works. For this line, I simply looked at how app.js
is imported.
<script defer phx-track-static type="text/javascript" src={Routes.static_path(@conn, "/assets/custom.js")}></script>
The next step would then be to figure out how to import it in a seperate template instead of the root. However, this first test already failed resulting in the following error:
[debug] ** (Phoenix.Router.NoRouteError) no route found for GET /assets/custom.js (MyAppWeb.Router)
(my_app 0.1.0) lib/phoenix/router.ex:405: MyAppWeb.Router.call/2
(my_app 0.1.0) lib/my_app_web/endpoint.ex:1: MyAppWeb.Endpoint.plug_builder_call/2
(my_app 0.1.0) lib/plug/debugger.ex:136: MyAppWeb.Endpoint."call (overridable 3)"/2
(my_app 0.1.0) lib/my_app_web/endpoint.ex:1: MyAppWeb.Endpoint.call/2
(phoenix 1.6.15) lib/phoenix/endpoint/cowboy2_handler.ex:54: Phoenix.Endpoint.Cowboy2Handler.init/4
(cowboy 2.9.0) c:/Users/arnod/Desktop/phoenixtut/my_app/deps/cowboy/src/cowboy_handler.erl:37: :cowboy_handler.execute/2
(cowboy 2.9.0) c:/Users/arnod/Desktop/phoenixtut/my_app/deps/cowboy/src/cowboy_stream_h.erl:306: :cowboy_stream_h.execute/3
(cowboy 2.9.0) c:/Users/arnod/Desktop/phoenixtut/my_app/deps/cowboy/src/cowboy_stream_h.erl:295: :cowboy_stream_h.request_process/3
(stdlib 4.0.1) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
Could somebody help me figure this one out? How does one add seperate Javascript files and only import them in specific templates?
You can import all your custom javascript once in app.js, assign them as hooks which you can then use in your (live) views, wherever needed, for example;
custom.js
export const SomeFunction = {
mounted() {
alert("some function ran!");
}
}
app.js snippet
...
import {SomeFunction} from "./custom.js"
let Hooks = {}
Hooks.SomeFunction = SomeFunction
let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
let liveSocket = new LiveSocket("/live", Socket, {params: {_csrf_token: csrfToken}, hooks: Hooks})
...
Then in your live view render function (or template) add the hook
...
def render(assigns) do
~H"""
...
<div id="my-hook" phx-hook="SomeFunction"></div>
...
end
...
More about javascript interoperability can be found on the Phoenix hex page here. You can tie them to all sorts of phoenix events.
nb. Also note that @conn isn't available in live views, only @socket is.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With