I don't think this is possible, because the assets in the static/
directory are not processed by Elixir, but by your asset pipeline (Brunch by default). They are pre-compiled so even if it worked, you would not have access to the @conn
variable, since this is not available at the time when static assets are compiled.
Keep in mind this is a good thing! The server does not need to re-render your Javascript on every page request.
You have several options to get the desired result:
Hard coding
Might seem hacky, but works well enough for simple cases. I recommend hard coding just a path, using //
at the start to preserve the current protocol (http/https). If you need to resolve this to a full URL, you can use this trick.
Data attributes
For one-off usage, you can add a data attribute to a related portion of your markup, for example for a login form:
<div id="create-user" data-url="<%= user_home_path(@conn, :create, userLogin) %>">
<!-- ... -->
</div>
Then in your JavaScript, you can access the data attribute. Note that depending on your use case, there might be a better way to retrieve the DOM node containing the data attribute than using document.querySelector
, this is just an example:
let createUserUrl = document.querySelector("#create-user").getAttribute("data-url");
If you only need to target IE11+ or willing to use a polyfill, you can also use dataset
let createUserUrl = document.querySelector("#create-user").dataset.url;
Or if you're using jQuery:
let createUserUrl = $("#create-user").data("url");
Maybe you'll be able to extract the URL from a different attribute such as the url
of a form
, should you be overriding the onclick
handler of the submit button, for example.
Add property on window
object
For truly global values, such as authentication tokens etc. you can set a property on the window
object, for example in web/templates/layout/app.html.eex
<script>window.userToken = "<%= assigns[:user_token] %>";</script>
then in your JavaScript, you can simply access
window.userToken
Other solutions
There are also more advanced solutions available for this problem, including:
Add a separate JSON endpoint that returns the required data as JSON which can then be requested from your JavaScript
If you use a JavaScript framework such as React.js, Vue.js, etc. you might be able to leverage routing logic from the framework or auxiliary JavaScript packages.
I'm sure there's even more options I didn't think of right now.