s-stepien
"Persistent" query string and navigating the pages
Hello
On the index page I have a search box that user can use to type a filter query:
<form phx-change="search" class="search-form">
<%= search_input :search_field, :query, placeholder: "Wyszukaj...", "phx-debounce": "300", value: @query %>
</form>
During typing, I’m generating phx-change (using debounce) that I handle in the event handler. That handler will generate updated assignments for the socket and the filtered view of the index page will be shown. And that works.
However, I need to somehow store the filter query string so it can be used also on the sub-pages too. Currently I’m storing the query string to the database (to given user’s row) and use it on sub-pages when I need.
And there comes the problem that I have: when user goes from sub-page to the index page (using browser back button or link provided on the sub-page [“back”]) the view of index is displayed as filter is not there (but it is there, since the input sets the value using: <%= search_input ...., "phx-debounce": "300", value: @query %>). So basically the phx-change event is not generated in that case.
How to overcome this? Maybe my architectural approach is incorrect in this context?
Most Liked
trisolaran
I hope I understood your problem. The way I deal with this kind of issues is as follows:
-
query string in URL changes → perform_search and update liveview
-
phx-change event → issue a
push_patchwith a query string corresponding to the new search input. The push_patch updates the query string and triggers (1)
This way the state of your view, search input and query string in the URL are always in sync.
In (simplified) code:
# This handles (1)
def handle_params(params, _uri, socket) do
search_input = params["search_field"] <-- This comes from the URL
{
:noreply,
assign(
socket,
seach_results: peform_search(search_field)
)
}
end
# This handles (2)
def handle_event(
"search",
%{"search_field" => search_field}, <-- This comes from the form input
socket
) do
{:noreply,
push_patch(socket,
to: Routes.api_path(socket, :your_live_view_page_name, search_field: search)
)}
end
# This handles the initial mount
def mount(params, _session, socket) do
{:noreply, socket} = handle_params(params, "", socket)
{
:ok,
socket
}
end
I hope this is what you were looking for.








