ux
ux copied to clipboard
[LiveComponent] `data-loading` attribute doesn't hide on AJAX complete when class is provided
On page load, an element can have both the data-loading
attribute and a class
. When an AJAX event is sent, the element correctly becomes visible to the user. However, when the AJAX event completes and the data-loading
element would typically hide, it doesn't if it has a class
attribute.
<div {{ init_live_component(this) }}>
<button class="shopping-cart-btn"
aria-label="{{ this.description }}"
data-action="live#action"
data-action-name="updateCart"
data-loading="addAttribute(disabled)"
>
<span data-loading="show" class="spin"> {# <= HERE #}
<i aria-hidden="true" class="bi-arrow-repeat"></i>
</span>
<span data-loading="hide">
<i aria-hidden="true" class="{{ this.icon }}"></i>
</span>
</button>
</div>
The way I was able to get around this problem is by separating the data-loading
and class
attributes into separate elements.
<div {{ init_live_component(this) }}>
<button class="shopping-cart-btn"
aria-label="{{ this.description }}"
data-action="live#action"
data-action-name="updateCart"
data-loading="addAttribute(disabled)"
>
<span data-loading="show"> {# <= HERE #}
<span class="spin">
<i aria-hidden="true" class="bi-arrow-repeat"></i>
</span>
</span>
<span data-loading="hide">
<i aria-hidden="true" class="{{ this.icon }}"></i>
</span>
</button>
</div>
I would expect that if the attribute combination works correctly on page load and AJAX start, then it would also work on AJAX complete.
I tried to reproduce this error in tests and in the live-demo but unfortunatly (?) i did not manage get this error.
Data-Loading show or hide does work for me with and without additional classes on the element. What i tried was
<small data-loading="show" class="TEST">SHOW ME</small>
<small data-loading="hide" class="TEST">HIDE ME</small>
<small data-loading="show">SHOW ME</small>
<small data-loading="hide">HIDE ME</small>
Does your class "spin" maybe add some css like a display inline or something ? The "hide" is done by css
[data-loading=""], [data-loading="show"], [data-loading="delay|show"] {
display: none;
}
Ah you are right, my .spin
class does indeed have a display: inline-block
.
Hm would it be reasonable to add !Important to the style to force the display none? Or set it as style attribute equally to the display lnline part.
I feel like it wouldnt be a clean solution. But maybe @weaverryan has an idea. At least we could add a Note in the docs
Hmm. I'm not sure about the best solution here! My initial reaction is that our CSS should add !important
on it. So:
[data-loading=""], [data-loading="show"], [data-loading="delay|show"] {
display: none !important;
}
Adding!important
is usually not something I love doing, however. And, I double-checked Livewire, and they (somehow) have similar CSS to us (no !important
) and I can't find any mention of problems over there.
In addition, or possibly "instead" of doing that, we should probably do the hiding with a style
attribute as mentioned. Well, to be clear: that IS how it works. Once you, for example, make your first Ajax request, hiding & showing is done via the style
attribute. The CSS only exists to try to hide elements correctly, on page-load, before any JS executes. To fix the situation we could, on connect()
of live controller, parse the components for data-loading
attributes and "process" those. For example, if we find an element with data-loader="show"
, we would hide the element (exactly like we would once an ajax request finishes). This would mean that:
A) On initial page load, the above CSS still immediately hides those elements. But... if it doesn't work for some reason like this, it is more of a minor problem.
B) very shortly after page load, the live controller JS correctly processes all the data-loading
attributes so that any elements that SHOULD be hidden, have display: none
style.
If someone would like to work on that, it would be appreciated :)
Cheers!
Thank you for this issue. There has not been a lot of activity here for a while. Has this been resolved?