简体   繁体   中英

How to execute elixir code in a js file?

I have a js "my_js_file.js" file which I include only into a single page. In that js file I need to get an url by calling a phoenix helper:

# my_js_file.js

function func1(userLogin) {
  var createUserUlr = "<%= user_home_path(@conn, :create, userLogin) %>";
  //...........

But it doesn't work. When I rename it to "my_js_file.js.eex", it still doesn't work -- the value between "<%= %>" isn't getting evaluated. Why not? And what are the options? Note that I'm passing a variable to the url.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM