floryan's avatar
Level 13

Property doesn't refresh in attribute

Hi,

Do Livewire properties even refresh when they are placed inside HTML attributes? I cannot get a property to refresh when I place it in a Bootstrap popover:

<td class="align-middle" style="height: 50px">
    <span class="ms-2">Costs List</span>
    <span
        data-bs-toggle="tooltip"
        data-bs-html="true"
        data-bs-title="{{ $costsList }}"
    ><i class="bi bi-question-octagon text-black opacity-50 ms-1"></i></span>
</td>

If they don't how to handle it?

0 likes
3 replies
LaryAI's avatar
Level 58

Livewire properties should indeed refresh in the HTML attributes when they change. However, for dynamic attributes like those used in Bootstrap tooltips or popovers, you may need to reinitialize the tooltip or popover when the Livewire component updates.

Here's a solution that uses Livewire's wire:ignore directive to prevent Livewire from updating the span element and its children. Instead, we'll manually reinitialize the popover whenever the Livewire component updates.

First, ensure that you have Alpine.js included in your project, as it plays nicely with Livewire for these types of interactions.

Then, update your Livewire component's view to something like this:

<td class="align-middle" style="height: 50px">
    <span class="ms-2">Costs List</span>
    <span
        x-data
        x-init="initPopover()"
        x-on:livewire-update.window="initPopover()"
        data-bs-toggle="tooltip"
        data-bs-html="true"
        data-bs-title="{{ $costsList }}"
        wire:ignore
    ><i class="bi bi-question-octagon text-black opacity-50 ms-1"></i></span>
</td>

<script>
    function initPopover() {
        document.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(el => {
            new bootstrap.Tooltip(el, {
                trigger: 'hover'
            });
        });
    }
</script>

Here's what's happening in the code:

  1. x-data initializes an Alpine.js component.
  2. x-init="initPopover()" calls the initPopover function when the Alpine.js component is initialized.
  3. x-on:livewire-update.window="initPopover()" listens for the livewire-update event on the window object, which Livewire dispatches after updating the DOM. When this event is fired, it calls the initPopover function again to reinitialize the popover.
  4. wire:ignore tells Livewire to ignore this span element and its children during DOM diffing, preventing Livewire from messing with the Bootstrap popover initialization.
  5. The initPopover function selects all elements with the data-bs-toggle="tooltip" attribute and initializes the Bootstrap tooltip on them.

This approach ensures that the popover content is updated when the Livewire property $costsList changes, and the popover itself is reinitialized to reflect the new content.

vincent15000's avatar

I really don't understand what you need ... do you need the property to update or not ?

Snapey's avatar

Look at it this way.

Livewire does not render any variables in the client.

It renders a blade view on the server and then sends that view to the client. Rather than update the whole html, Livewire does a diff against the existing dom and decides what bits have changed.

So there is no way that livewire would ignore html attributes. Its pasting in the whole html.

But, you should consider, if this td is inside a for each loop, have you used wire:key to ensure that Livewire knows which row its dealing with?

1 like

Please or to participate in this conversation.