Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

jj63systems's avatar

Interference between javascript onclick and livewire

Hi I am trying to implement something probably extremely common. A page has a search box and, on submit, search results are displayed below. The user can click a "heart" icon against items returned - and this should do two things

  • change the visual appearance of the icon (javascript)
  • update the database (php within the controller).

The first block of the blade (search field) is coded thus

<x-filament-panels::page>
    <div>
        <form wire:submit.prevent="search">
            {{ $this->form }}

            <div style="margin-top: 8px;">
                <x-filament::button
                    type="submit"
                    onclick="hideResults();"
                    wire:loading.attr="disabled"
                    wire:loading.class="bg-gray-300 text-gray-600">
                    <span wire:loading class="animate-pulse bg-gray-500">Processing...</span>
                    <span wire:loading.remove>Search</span>
                </x-filament::button>
            </div>
        </form>

And the search results is coded thus

Now the problem is that when I click the icon (the svg) it fires the onclick which changes the colour (I have omitted the javascript) but IT ALSO seems to change the submit button (to say "Processing") and, although the DB query isn't repeated, the results div is updated again (which then resets the icon to its original colour).

Can anyone help on this?

thanks :) j

0 likes
11 replies
vincent15000's avatar

I see 3 possible conflict causes : Filament vs Livewire vs JS.

If you are using Livewire, you should better use AlpineJS rather than Vanilla JS.

Snapey's avatar

Your SVG is inside the button, and both have onclick attributes. If you don't prevent default on the svg click event, the button wire:click will also be fired.

1 like
jj63systems's avatar

@Snapey Sorry if this is a basic js question - but how would I "prevent default on the SVG click"?

Or do I not need the button element at all?

thanks for your help, j

1 like
jj63systems's avatar

@Snapey Hi sorry if i’m being thick, but are you able to explain this a little more?

1 like
jj63systems's avatar

Hi giving an update on what I have learned & tried - but as yet, still unsuccessful. The behaviour seems to be that as soon as I call the function toggleState (a function defined within the controller) then it seems trigger the button label change and re-rendering of the search results.

I tried adding the wire:click to different elements (the SVG definition, its surrounding div, the button ) - all with no change in behaviour.

I then modified the js which is responsible for changing the colour of the SVG and used Livewire.dispatch - no change (code shown here for reference).

    function changeIconColor(id, event) {

        const heroicon = document.getElementById(`heroicon${id}`);
        const currentFill = window.getComputedStyle(heroicon).getPropertyValue('fill');

        // use the current colour as a boolean
        if (currentFill == 'none')
            heroicon.style.fill = 'red';
        else
            heroicon.style.fill = 'none';
        console.log('about to livewire.dispatch using id' + id);
        Livewire.dispatch('toggle-state', {
            id: id,
            isActive: true
        })

    }

To be clear, the SVG is changing colour and the toggleState function is being called - I just need to find a way to call this (or another function) so that it doesn't trigger whatever it is that causes the refreshing. I have tried passing the event into the function and then using event.stopPropagation (and even written the event to console to be sure) but no difference in behaviour has been observed.

To remind you, dear patient readers on this, the final fay of 2024, this is code within a blade that was created as the result of creating a "custom page" in Filament (v3) - is it possible that there is something "higher up" that's not in my blade that is influencing this behaviour?

1 like
jj63systems's avatar

@vincent15000 Hi thanks for the suggestion, but it makes no difference, sadly. The search input here was just a text field and a submit button - I have evolved this to include some checkboxes to allow the user to refine what should be returned by the search (future feature). What I notice is that if I check / uncheck these then the same behaviour occurs. Now, there is some relationship between these checkboxes (such as a select all / select none feature) which I guess involves the controller.

So the cause (?) of my problems appears to be any invocation of a function in the controller.

Does this make any sense?

Happy new year! (5hours and 36 minutes remaining) :)

1 like
jj63systems's avatar

@Snapey Hi this looks like exactly what I need. However, it doesn't implement the required behaviour.

I tried both this

    #[Renderless] 
    public function toggleState($id, $isActive)
    {
        // Update the database here
        Log::info('toggleState - id=' . $id);
    }

and this

    public function toggleState($id, $isActive)
    {
        $this->skipRender(); 
        // Update the database here
        Log::info('toggleState - id=' . $id);
    }

and together

    #[Renderless] 
    public function toggleState($id, $isActive)
    {
        $this->skipRender(); 
        // Update the database here
        Log::info('toggleState - id=' . $id);
    }

But no change.

I'm wondering - on the page you referred me to the example is of a "component" whereas mine is a filament "page" - i.e. the examples start

class ShowPost extends Component

whereas mine starts

class ResearchHome extends Page

And perhaps that's why this approach isn't working - really appreciate any additional insights you might have.

Oh and happy new year :)

j

1 like

Please or to participate in this conversation.