robinmonjo

robinmonjo

Ajax call in phoenix (respond_to :js in rails)

Hello everyone,

I have been spending some times Googling but didn’t find anything. In rails there is a way to do ajax call like this:

link_to some_path, remote: true

Then we can accept the js format controller side and render a view.js.erb that executes some JS directly on the page.

I wonder if this is doable in Phoenix. Should I write raw javascript ? Or is there something similar than in rails ?

Regards,
Robin

Most Liked

yurko

yurko

I call the functions from the service layer (that use models) that return :ok or error tuples, same as you do in controllers.

To avoid having too much dom manipulation I render templates to strings (same partials that are used on render) and pass them to frontend, so channels work much like controllers.

On the front end you might get away with jQuery (I did in the latest app), since there’s not much JS this way. For a proper SPA I’d go for Vue or React or something.

It’s not easy to deliver an example without over-simplifying or polluting it with non relevant parts, I’ll do my best though, hope it still paints a picture :slight_smile:

// some_socket.js 
// import base socket stuff and create a socket / channel vars
const getItems = (opts, onSuccess, onError) => {
  base.pushMessage(channel, "get-items", opts, onSuccess, onError);
};

export {someSocket as socket};
export {getItems as getItems};


// some_template_partial.html.eex
let someSocket = require('app/some_socket');
someSocket.socket.connect();

let onSuccess = function(response) {
  $("#partial-id").replaceWith(response.some_html_string);
  // render info notification
}
let onError = function(response) {
  // render error notification
}

$someElement.click(function(e){
    e.preventDefault();
    // get relevant data from dom
    someSocket.getItems(data, onSuccess, onError);
});


 // some_channel.ex
 def handle_in("get-items", payload, socket) do         
   case SomeService.get_items(payload) do
     {:ok, items} ->
       html = render_to_string(LayoutView, "partials/some.html", [socket: socket,  items: items])
       {:reply, {:ok, %{some_html_string: html}}, socket}
     {:error, reason} -> {:reply, {:error, %{reason: reason}}, socket}
   end
 end

Also check out Drab and Unpoly as suggested by @OvermindDL1 - they use similar idea but provide more abstractions.

What I find nice about this approach - it’s pretty clean and organized (despite all the love jQuery front ends get), very fast (often feels like working offline) and you get less rituals with all the actions, api routes etc that you get when working with AJAX.

murtza

murtza

Rails uses jquery-ujs to perform ajax calls and you can use it in your phoenix project by making little changes. i.e you can copy jquery-ujs/src/rails.js at master · rails/jquery-ujs · GitHub into your app.js and change csrf-token to _csrf_token as following

// Up-to-date Cross-Site Request Forgery token
csrfToken: function() {
   return $('meta[name=_csrf_token]').attr('content');
},

Now you can add "data-remote": "true" in form_for and your form will be submitted as xhr request. for example.

<%= form_for @changeset, @action, ["data-remote": "true"], fn f -> %>

You can add render(conn, "create.js.eex") in your controller just like rails.

i haven’t tested it yet but i hope it will work.

aseigo

aseigo

Sort of in left field here, but depending on what you are trying to do … you may be able to use the UserSocket instead which in theory should be lighter weight / faster. The client would send it’s request over the websocket and it would respond with the appropriate data, which the client would then act on. Just a thought…

Where Next?

Popular in Questions Top

sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
Tee
can someone please explain to me how Enum.reduce works with maps
New
qwerescape
Is there a way to get the call stack or stack trace at any point in the code? Not from exceptions, but an expression that returns how the...
New
mgjohns61585
Could someone help me? I’m making my first elixir program, number guessing game. I can’t figure out how to convert the user’s guess from ...
New
ycv005
I have followed this StackOverflow post to install the specific version of Erlang. And When I am running mix ecto.setup then getting fol...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
srinivasu
How to handle excepions in elixir? Suppose i have A, B, C ,D, E modules. and each module has get() function. A.get() method will call t...
New
yawaramin
In the Dialyzer docs ( dialyzer — OTP 29.0.2 (dialyzer 6.0.1) ), there is a way to turn off a specific warning for a function: -dialyzer...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New

Other popular topics Top

danschultzer
None of the current solutions worked well for me, so I went ahead and built a user management system from scratch. This project took far...
548 29603 241
New
Darmani72
If I have a post route which an argument: post /my_post_route/:my_param1, MyController.my_post_handler How would get the post params ...
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
johnnyicon
Hi all, I’ve just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I’m trying to use Postgres...
New
AngeloChecked
What learn first? Rust or Elixir Hi Elixir community! I’m here because i want learn a new language. I’m a junior developer and mainly i ...
New
Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I forese...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New

Latest on Elixir Forum

Elixir Forum

We're in Beta

About us Mission Statement