Hello there!
I have this LiveView from Mike Clark’s LiveView course and it works just perfect if I don’t use temporary_assigns
. If I search for stores by zip and then by city, if there are no matches for that city it will clear the list as expected, but if I do the same search and use temporary_assigns, the HTML is not cleared and keeps the first results.
I believe is because even when the state is cleared(in the city-search
event) making the stores
property an empty list, the update is not pushed back because the store state value was already an empty list because the temporary_assigns
.
If you have suggestions on how to make it work. Thank you!
defmodule LiveViewStudioWeb.AutocompleteLive do
use LiveViewStudioWeb, :live_view
alias LiveViewStudio.Stores
alias LiveViewStudio.Cities
def mount(_params, _session, socket) do
socket =
assign(socket,
zip: "",
city: "",
stores: [],
matches: [],
loading: false
)
{:ok, socket, temporary_assigns: [stores: [], matches: []]}
end
def render(assigns) do
~L"""
<h1>Find a Store</h1>
<div id="search">
<form phx-submit="zip-search">
<input type="text" name="zip" value="<%= @zip %>"
placeholder="Zip Code"
autofocus autocomplete="off"
<%= if @loading, do: "readonly" %> />
<button type="submit">
<img src="images/search.svg">
</button>
</form>
<form phx-submit="city-search" phx-change="suggest-city">
<input type="text" name="city" value="<%= @city %>"
placeholder="City"
autocomplete="off"
list="matches"
phx-debounce="1000"
<%= if @loading, do: "readonly" %> />
<button type="submit">
<img src="images/search.svg">
</button>
</form>
<datalist id="matches">
<%= for match <- @matches do %>
<option value="<%= match %>"><%= match %></option>
<% end %>
</datalist>
<%= if @loading do %>
<div class="loader">
Loading...
</div>
<% end %>
<div id="stores" class="stores">
<ul>
<%= for store <- @stores do %>
<li>
<div class="first-line">
<div class="name">
<%= store.name %>
</div>
<div class="status">
<%= if store.open do %>
<span class="open">Open</span>
<% else %>
<span class="closed">Closed</span>
<% end %>
</div>
</div>
<div class="second-line">
<div class="street">
<img src="images/location.svg">
<%= store.street %>
</div>
<div class="phone_number">
<img src="images/phone.svg">
<%= store.phone_number %>
</div>
</div>
</li>
<% end %>
</ul>
</div>
</div>
"""
end
def handle_event("zip-search", %{"zip" => zip}, socket) do
send(self(), {:run_zip_search, zip})
socket =
assign(socket,
zip: zip,
stores: [],
loading: true
)
{:noreply, socket}
end
def handle_event("city-search", %{"city" => city}, socket) do
send(self(), {:run_city_search, city})
socket =
assign(socket,
city: city,
stores: [],
loading: true
)
{:noreply, socket}
end
def handle_event("suggest-city", %{"city" => prefix}, socket) do
socket = assign(socket, matches: Cities.suggest(prefix))
{:noreply, socket}
end
def handle_info({:run_zip_search, zip}, socket) do
case Stores.search_by_zip(zip) do
[] ->
socket =
socket
|> put_flash(:info, "No stores matching \"#{zip}\"")
|> assign(stores: [], loading: false)
{:noreply, socket}
stores ->
socket = assign(socket, stores: stores, loading: false)
{:noreply, socket}
end
end
def handle_info({:run_city_search, city}, socket) do
case Stores.search_by_city(city) do
[] ->
socket =
socket
|> put_flash(:info, "No stores matching \"#{city}\"")
|> assign(stores: [], loading: false)
{:noreply, socket}
stores ->
socket = assign(socket, stores: stores, loading: false)
{:noreply, socket}
end
end
end