adityar15's avatar

Livewire dom diffing issue for pagination and bootstrap modal

So the problem is kind of a complex one. I have a list of items that I am fetching from the database with custom pagination. The reason for custom pagination is I need to call API through a livewire component.

In a blade file (normal view file) I have two livewire components

@livewire('items')
@livewire('modalcomponent')

<script>
    window.addEventListener('showmodal', () => {
        Livewire.emit('rendermodalcontent');
        
	var m = new bootstrap.Modal(document.querySelector('#modalid'), {
            keyboard: true
        })
     
    m.show()
    });
</script>

Each item has a button that triggers the bootstrap modal depending upon a condition. The bootstrap modal is in modalcomponent and the file looks something like this

<div class="modal fade" wire:key=modalid id="modalid" tabindex="-1" 
aria-labelledby="modalid" aria-hidden="true" wire:ignore.self>

//modal content

</div>


in my items component blade file, I have something like this

<div>

<div>
//some html

<button class='btn btn-danger' wire:click='triggermodal'>Trigger Modal</button>
</div>

<button class='btn btn-primary' wire:click='showmoreitems'>Show More</button>

</div>

In the controller file, the code looks like this,

class Items extends Component
{
    public $items=[] $lastpage=99999999999, $current=0, 
    $complete=false;


    public function render()
    {
        return view('livewire.items');
    }


    public function mount(){     
       $this->showmoreitems();
    }

public function triggermodal(){
	if($condition == true){
	$this->dispatchBrowserEvent('showmodal'); //defined in the view file
}
}

    public function showmoreitems(){
        $this->current += 1;
        if($this->current <= $this->lastpage)
        {
            $this->fetch();
        }
        else{
            $this->complete = true;
        }

    }



 public function fetch(){
       
        $this->dispatchBrowserEvent('loading');
        
        $take = 5;

        $datatosendapi                = [
            'page'    => $this->current,
            'take'    => $take,
        ];
	
	//api call


 $this->items =  array_merge($this->items, $response);


       


        $this->dispatchBrowserEvent('loading-complete');
    }



}

Now what's happening is when I load the page for the first time, the modal works fine. However, as soon as I fetch more items and trigger the modal for newly fetched items, the screen becomes dark grey (same as modal background) after I close the modal. The entire HTML does not respond to any clicks or events.

The modal has dynamic content loaded in it and it is rendered with new content every time it is triggered.

I am using Bootstrap 5.

Why is the modal is behaving weirdly? Am I missing something?

Thanks in advance :)

0 likes
2 replies
chaudigv's avatar

Let's try to cover few grounds step-by-step.

First, have only ONE parent div

<div>
    @livewire('items')
    @livewire('modalcomponent')
</div>

In your Model Component, you are missing quotes

wire:key="modalid"

I do not see any place where $condition value is changing.

does not respond to any clicks or events.

Because the gray background has a z-index and expecting the modal (with higher z-index) to show but due to some error that ins't happening.

Please format your question.

adityar15's avatar

@chaudigv Thanks for the answer. I tried all your ways but it didn't work.

However, I made it work with a bit of JavaScript. So bootstrap modal has event events and I was listening to the hidden.bs.modal event. On this event, I am hiding the modal again with javascript.

Something like this,

var hiddenflag=false;
window.addEventListener('hidden.bs.modal', ()=>{

var myModalEl = document.getElementById('myModal')
!hiddenflag ? myModalEl.hide() : window.removeEventListener('hidden.bs.modal', ()=>{})
hiddenflag=true;

});

It's an awkward solution but this the only one which worked.

Please or to participate in this conversation.