My desired behavior is to update a html.leex table depending of whether or not I have a checkbox checked.
The problem is that my leex table has erractics behaviors on browsers.
On Safari, the toggle doesn’t change visually, yet the table update itself correctly.
On Firefox, it’s the toggle that work well, and the table that has updated data yet doesn’t update itself.
Here is my module
@impl true
def mount(_params, _session, socket) do
socket = assign(socket, examens: []) # As mount is called twice, this is the default state
socket =
case connected?(socket) do # This piece is executed only once, while mount itself is called twice
true -> setup_socket_assigns(socket)
false -> socket
end
{:ok, socket}
end
@impl true
def handle_event("hidecheck", _params, %{assigns: %{checked: checked}} = socket) do
socket = assign(socket, checked: !checked) # Update toggled
IO.inspect(socket.assigns.checked, label: "\n\nStatus of the checkbox")
socket =
case socket.assigns.checked do
true -> hide_common_exams(socket)
false -> show_every_exams(socket)
end
#IO.inspect(socket.assigns.__changed__, label: "List of changes in assigns")
#IO.inspect(Enum.count(socket.assigns.examens), label: "Number of exams")
{:noreply, socket}
end
# Setup the socket when connected. Pipe compatible
def setup_socket_assigns(socket) do
IO.inspect("Socket connected, second mount call, setting up exams")
socket
|> assign(checked: false)
|> show_every_exams()
end
# If toggle is active, this with do the assign in the socket. Pipe compatible
def hide_common_exams(socket) do
IO.inspect("Hide commons exams")
examens = Examens.list_unique_examens()
socket
|> assign(examens: examens)
#|> IO.inspect()
end
# If toggle is not active, this will do the assign in the socket. Pipe compatible
def show_every_exams(socket) do
IO.inspect("Show every exams")
examens = Examens.list_examens()
socket
|> assign(examens: examens)
#|> IO.inspect()
end
My table
<h2>Liste des examens</h2>
<% IO.inspect @examens %> # Print updated data
<table>
<thead>
<tr>
<th>Accession Number</th>
<th>Nom</th>
<th>Patient ID</th>
<th>Naissance</th>
<th>AET</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<%= for examen <- @examens do %>
<tr>
<td><%= examen.accession_number %></td>
<td><%= examen.name %></td>
<td><%= examen.patient_id %></td>
<td><%= dayFormatter(examen.birthday) %></td>
<td><%= examen.aet %></td>
<td><%= examen.type %></td>
</tr>
<% end %>
</tbody>
</table>
Live.html.heex (This toggle is straight up taken from W3C)
<div class="hidetoggle">
<!-- Rounded switch for merging boards-->
<label class="switch">
<input type="checkbox" phx-click="hidecheck" {checked: @checked}>
<span class="slider round"></span>
</label>
<h3 class="labeltoggle">Hide examens both in modalities and archives</h3>
</div>
hello , i think your error is on this line on the hidecheck event
socket = assign(socket, checked: !checked) # Update toggled
remember that at this point the socket has the updated check property updated, but after that
you do
socket =
case socket.assigns.checked do
true → hide_common_exams(socket)
false → show_every_exams(socket)
end
so the socket is not the same you assign earlier is the one pass down to the function
you can pipe the changes
socket =
case socket.assigns.checked do
true → hide_common_exams(socket)
false → show_every_exams(socket)
end
|> assign(socket, checked: !checked)
Thanks for trying, but this part has the precise behavior I wish (inverse the bool, then compute result according to it).
I know because each time I toggle, my examen list is correctly updated, both in the handle_event (the commented IO.inspect) and in the template (the IO.inspect @examens above the table in html.leex)
It just happen than even if the template has new data and is called (the IO.inspect print logs just fine), the webpage is not updated correctly in my browsers. Seem like a problem due to web browsers, but I didn’t read anything about limited supports for some browsers in the LiveView documentation.
After more testing, I found out that commenting this line
socket = assign(socket, checked: !checked) # Update toggled
Allow safari to correctly display the checkbox. I truly don’t get how an assign in the socket could reset the checkbox status. The boolean isn’t updated, so I don’t see why.
In fact, it seem that no matter the browser, only one thing can update the view. Either the browser when checking the box, or the liveview updating the array. Both can’t do it at the same time. I seldomly got the toggle working without array update on Firefox, or Array without toggle on Safari.
Ok I am no dev web, so it took a while to get more info, but look like Firefox received the update array well, according to the web console. However, it raised a “Uncaught DOMException: String contains an invalid character”
Here is the full execption, even if do not know yet what it mean
Uncaught DOMException: String contains an invalid character dom.js:276:37
mergeAttrs dom.js:276
mergeFocusedInput dom.js:292
onBeforeElUpdated dom_patch.js:181
morphEl morphdom-esm.js:490
morphChildren morphdom-esm.js:603
morphEl morphdom-esm.js:505
morphChildren morphdom-esm.js:603
morphEl morphdom-esm.js:505
morphChildren morphdom-esm.js:603
morphEl morphdom-esm.js:505
morphChildren morphdom-esm.js:603
morphEl morphdom-esm.js:505
morphdom2 morphdom-esm.js:720
perform dom_patch.js:95
time live_socket.js:229
perform dom_patch.js:94
performPatch view.js:374
update view.js:480
time live_socket.js:229
update view.js:477
hookReply view.js:674
applyDiff view.js:227
pushWithReply view.js:673
after live_socket.js:812
requestDOMUpdate live_socket.js:247
pushWithReply view.js:672
matchReceive push.js:76
forEach self-hosted:164
matchReceive push.js:76
startTimeout push.js:107
trigger channel.js:278
Channel channel.js:70
trigger channel.js:278
onConnMessage socket.js:510
decode serializer.js:25
decode self-hosted:1118
onConnMessage socket.js:497
onmessage socket.js:221
(Asynchrone : EventHandlerNonNull)
connect socket.js:221
doConnect live_socket.js:208
connect live_socket.js:212
<anonyme> app.js:38
<anonyme> app.js:5011
And here is the data that was pushed to add entry to the array:
2: Array(6) [ "A000001", "SIMPSON^Homer", "004025792", … ]
0: "A000001"
1: "SIMPSON^Homer"
2: "004025792"
3: "07/06/1965"
4: "RADIO_PGR"
5: "archive"
length: 6
<prototype>: Array []
3: Array(6) [ "A000002", "SIMPSON^Bart", "004025756", … ]
0: "A000002"
1: "SIMPSON^Bart"
2: "004025756"
3: "07/12/2005"
4: "ECHO_PGR"
5: "archives"
length: 6
Safari doesn’t raise.
Right now I think I’ll try with a classic button instead of a checkbox
OK I made everything work, the problem was that leex was depreciated and renaming live.html.leex into heex solved everything.
That was rather frustrating, but at least now it works.
And the worst is that I put the correct name in my problem.
Just in case tho, the input should be
<input type="checkbox" phx-click="hidecheck" checked={@checked}>
Watch out for attibute settings in templates.