Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elixir Phoenix - How to create and import javascript files into specific templates

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?

like image 570
Astarno Avatar asked Sep 01 '25 10:09

Astarno


1 Answers

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.

like image 56
Hedde van der Heide Avatar answered Sep 04 '25 00:09

Hedde van der Heide