LiveView collapses my opened element.
I have an element that starts off as being collapsed on page load:
<a class="collapse_trigger">...</a>
<div class="is-collapsible">
# content updated by liveview
</div>
If a user clicks on the collapsible, the collapsible has a class .is-active
.
<a class="collapse_trigger">...</a>
<div class="is-collapsible is-active">
# content
</div>
But liveview removes that class. Any idea how I can make sure that liveview ignores the parent element <div class="is-collapsible is-active">
but takes care of the children?
My first thought was phx-update="ignore"
. But now I'm thinking I need to put the logic of the collapsible into the backend. :/
I use bulma-collapsible with one css change:
// the following is necessary because liveview does not work well with the bulma-collapsible. Otherwise elements would stay open but can be closed by clicking them twice.
.is-collapsible{
height: 0;
&.is-active{
height: auto;
}
}
In order to use front-end only options I advise the following.
For simplicity I will use plain javascript.
We need to modify button, and write function to store state (I used simple localStorage)
<a class="collapse_trigger" onclick="memoizeCollapsibleState()">...</a>
<script type="text/javascript">
function memoizeCollapsibleState() {
if (!localStorage.getItem('collapsibleState')) {
localStorage.setItem('collapsibleState', true)
} else {
localStorage.removeItem('collapsibleState')
}
}
</script>
afterwards we need to write function that will restore that state from localstorage
function restoreCollapsibleState() {
var collapsibleEl = document.getElementById('collapseExample');
if (localStorage.getItem('collapsibleState')) {
collapsibleEl.classList.add('is-active')
}
}
And final moment we need to bind that function to phoenix_live_view
socket update, we need to do it right after window has been loaded.
window.onload = init;
function init() {
liveSocket.getSocket().channels[0].onMessage = function (e, t, n) {
setTimeout(restoreCollapsibleState, 10)
return t
}
}
The purpose of setTimeout
function is that socket updates is async operation, and we need to add some delay in order to have collapsible state restored. 10ms seems to be ok, but we can change it to any other debounce function, I just used it for simplicity, consider this is as proof of concept
I just made an example with default live phoenix structuremix phx.new my_app --live
Added bootstrap to it (but I think bulma follows mostly the same rules) And modified phoenix live template to the following
<div class="collapse <%= if (@results && String.trim(@query) != ""), do: "show", else: "" %>" id="collapseExample">
<div class="card card-body">
<%= for {app, _vsn} <- @results do %>
<p value="<%= app %>"><%= app %></p>
<% end %>
</div>
</div>
so if there are any results and query is not empty thus will not be ever collapsed.
For your case I think it will be slightly the same
<a class="collapse_trigger">...</a>
<div class="is-collapsible <% if (@results && String.trim(@query) != "") do: "is-active", else: "" %>">
# content
</div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With