Search code examples
javascriptlaravellaravel-livewirealpine.jsgridstack

Livewire listen to event changes from a JS library


I'm trying to incorporate a js library, gridstack, with livewire/apline.js. Unfortunately, there really are no resources online on how to make it work with livewire. I'm not that familiar with js, hence why I use the TALL stack for development but after much research gridstack is the best solution for us.

Can anyone point me in the right direction on how to listen to events js libraries provide so I can connect with livewire?

This is what I have so far and my interactive grid loads correctly. I need to be able to listen for a change that happens when an item is moved/resized/dragged so I can save it in the backend with livewire/laravel.

<div
    x-data="{
        init() {
            let grid = GridStack.initAll({
                column: 6,
                cellHeight: '60px',
                cellWidth: '100px',
                float: false,
                resizable: {
                    handles: 'e'
                },
                margin: 2
            })
        }
    }"
  >
  <div class="grid-stack">
     <div class="grid-stack-item">
        <div class="grid-stack-item-content">Item 1</div>
     </div>
     <div class="grid-stack-item" gs-w="2">
        <div class="grid-stack-item-content">Item 2 wider</div>
     </div>
  </div>


    @assets
        <script src="https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/10.1.2/gridstack-all.js" defer></script>
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/10.1.2/gridstack.min.css">
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/10.1.2/gridstack-extra.min.css">
    @endassets
</div>

This is from the gridstack api and I believe is what I need to incorperate with my code.

change(event, items)

Occurs when widgets change their position/size due to constrain or direct changes

grid.on('change', function(event: Event, items: GridStackNode[]) {
  items.forEach(function(item) {...});
});

Edit

Ultimetley I arrived at this, from comment input and works great:

init() {
    let grids = GridStack.initAll({
        column: 6,
        cellHeight: '60px',
        cellWidth: '100px',
        float: false,
        resizable: {
            handles: 'e'
        },
        margin: 2
    });

    grids.forEach(element => {
        element.on('change', function(event, items) {
            let newItems = [];

            items.forEach ((el) => {
                newItems.push({_id: el._id, x: el.x, y: el.y, w: el.w, task_id: el.id});
            });

            $wire.taskMoved(newItems);
        });
    });
}

Solution

  • It depends on the information you need, however this example gives you an idea of ​​what can be done:

    The class

    namespace App\Livewire;
    
    use Livewire\Component;
    
    class GridStack extends Component
    {
        public function setItems ($items)
        {
            dd ($items);
        }
    }
    

    Te view:

    <div
        x-data="{
            init() {
                let grid = GridStack.init({
                    column: 6,
                    cellHeight: '60px',
                    cellWidth: '100px',
                    float: false,
                    resizable: {
                        handles: 'e'
                    },
                    margin: 2
                });
    
                grid.on('change', function(event, items) {
    
                    let newItems = [];
    
                    items.forEach ((el) => {
                        newItems.push({_id: el._id, x: el.x, y: el.y});
                    });
    
                    $wire.setItems(newItems);
                });
            }
        }"
    >
    
        <div class="grid-stack" wire:ignore>
            <div class="grid-stack-item">
                <div class="grid-stack-item-content">Item 1</div>
            </div>
            <div class="grid-stack-item" gs-w="2">
                <div class="grid-stack-item-content">Item 2 wider</div>
            </div>
        </div>
    
    
        @assets
            <script src="https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/10.1.2/gridstack-all.js" defer></script>
            <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/10.1.2/gridstack.min.css">
            <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/10.1.2/gridstack-extra.min.css">
        @endassets
    </div>
    

    In the init() function of the Alpine section is set the event handler, it calls the backend method via the $wire object