zamith

zamith

LiveView push_patch append to params

I’m creating a search form with filters and want both the query and the filters to change the URL. The filters and query can be set separately or together, and handle_params can already deal with either being empty.

What I’m doing is triggering a push_patch on events (filter click, form submit, clear search). Something like this:

  def handle_event("update_filter", %{"filter" => filter}, socket) do
    {:noreply,
     push_patch(socket,
       to: Routes.live_path(socket, Index, query: socket.assigns.query, filter: filter)
     )}
  end

  def handle_event("search", %{"query" => query}, socket) do
    {:noreply,
     push_patch(socket,
       to: Routes.live_path(socket, Index, query: query, filter: socket.assigns.filter)
     )}
  end

This works, but my “problem” is that I have to set all the url params every time I call push_patch. Is there any way to say append this param to the current path? Alternatively, is there any other design pattern I should be following to set this up?

Most Liked

josevalim

josevalim

Creator of Elixir

Here is how I solved it in my app:

  1. I store the params in handle_params as part of the assigns:

     def handle_params(params, url, socket) do
       # You could store the params as is but I like to store
       # only what has been parsed/validated.
       params = parse_params(params)
       {:noreply, assign(socket, :params, params)
     end
    
  2. Create a helper called self_path:

     def self_path(socket, action, extra) do
       Routes.live_path(socket, __MODULE__, action, Enum.into(extra, socket.assign.params))
     end
    
  3. Now I do:

     push_path(socket, to: self_path(socket, :search, %{"sort_by" => "foo"}))
    
19
Post #8
sb8244

sb8244

Author of Real-Time Phoenix

FWIW, you can also directly use the URI rather than calling the Routes helpers. The above code does this as well, but I wanted to provide a more concise version if you don’t need as many bells and whistles.

  def handle_params(_params, uri, socket) do
    {:noreply, assign(socket, :uri, URI.parse(uri))}
  end

  def handle_event("prev_page", _, socket = %{assigns: %{pager: %{page: page}, uri: uri}}) do
    current_params = URI.decode_query(uri.query || "")
    new_params = Map.put(current_params, "page", page - 1)
    to = uri.path <> "?" <> URI.encode_query(new_params)

    {:noreply, push_patch(socket, to: to)}
  end
seva

seva

Worth adding that instead of URI.decode_query/1 and URI.encode_query/1, you might want to use more robust Plug.Conn.Query.decode/1 and Plug.Conn.Query.encode/1, which do better encoding/decoding of lists in URL (e.g. ?ids[]=1&ids[]=2).

I.e.

URI.decode_query("ids[]=1&ids[]=2")
# => %{"ids[]" => "2"}

Plug.Conn.Query.decode("ids[]=1&ids[]=2")
# => %{"ids" => ["1", "2"]}

Where Next?

Popular in Questions Top

hariharasudhan94
lets say i have a sample like a = 20; b = 10; if (a &gt; b) do {:ok, "a"} end if (a &lt; b) do {:ok, b} end if (a == b) do {:ok, "equa...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
shahryarjb
Hello, I get Persian date from my client and convert it to normal calendar like this: def jalali_string_to_miladi_english_number(persi...
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
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
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

lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
mcarvalho
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
greenz1
I have a phoenix application from which a user can download multiple(5-6) files of size 1MB. I couldn’t find anything related to sending ...
New
gausby
I asked this very same question on twitter and got some interesting feedback, but I thought it would be a good question to ask here as we...
1207 39523 209
New
RisingFromAshes
I’ve read in another post that it may be possible with a router helper - but I couldn’t find an appropriate one, and tbh, I’m still just ...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
Qqwy
Update: How to use the Blogs &amp; Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3271 127536 1222
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 54250 245
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New

We're in Beta

About us Mission Statement