Skip to content

Ajax batch action not working? #3190

Closed
yajra/laravel-datatables-html
#227
@Seb33300

Description

@Seb33300
Contributor

In the laravel-datatables-vite repository, I found an interesting ajax batch feature that is supposed to be used by creating a button like this:

 Button::make('ajaxBatch')
     ->text('Restore')
     ->url(route('batch-restore-action-url'))
     ->confirmation('Generic confirmation message.') // Optional if you want confirmation before proceeding.
     ->onCancel('function(response) { alert("confirmation cancelled") }')
     ->onSuccess('function(response) { alert("success") }')
     ->onError('function(err) { alert("error") }')

See: https://github.com/yajra/laravel-datatables-vite/blob/51a126ec6020b7f3b97715e3e08af07c5be4f781/js/buttons/ajaxBatch.js#L6-L12

Unfortunately, if I try to use it in my Datatable class, this mails with the following error:

Method Yajra\DataTables\Html\Button::url does not exist.

I cannot find any reference of any of those methods in Laravel Datatables.

Did I miss something?

Activity

changed the title [-]Batch action not working?[/-] [+]Ajax batch action not working?[/+] on Nov 6, 2024
yajra

yajra commented on Nov 6, 2024

@yajra
Owner

Thanks for reporting, it appears that the magic method from the Fluent class breaks when the Macroable trait was added via: yajra/laravel-datatables-html#224

I tried to play with that script and this is the workaround for now:

  1. Register a macro to set the attributes (this was magically added by Fluent class before the patch)
        Button::macro('url', function(string $url) {
            $this->attributes['url'] = $url;

            return $this;
        });
        Button::macro('confirmation', function(string $confirmation) {
            $this->attributes['confirmation'] = $confirmation;

            return $this;
        });
        Button::macro('onCancel', function(string $onCancel) {
            $this->attributes['onCancel'] = $onCancel;

            return $this;
        });
        Button::macro('onSuccess', function(string $onSuccess) {
            $this->attributes['onSuccess'] = $onSuccess;

            return $this;
        });        
        Button::macro('onError', function(string $onError) {
            $this->attributes['onError'] = $onError;

            return $this;
        });
  1. Register your button in the HTML builder
            Button::make('ajaxBatch')
                ->text('Restore')
                ->url(route('users.index'))
                ->confirmation('Generic confirmation message.') // Optional if you want confirmation before proceeding.
                ->onCancel('function(response) { alert("confirmation cancelled") }')
                ->onSuccess('function(response) { alert("success") }')
                ->onError('function(err) { alert("error") }'),
  1. Integrate the ajaxBatch.js script.
/**
 * DataTables Batch Ajax action button.
 *
 * -- Laravel Integration --
 *
 * Button::make('ajaxBatch')
 *     ->text('Restore')
 *     ->url(route('batch-restore-action-url'))
 *     ->confirmation('Generic confirmation message.') // Optional if you want confirmation before proceeding.
 *     ->onCancel('function(response) { alert('confirmation cancelled') }')
 *     ->onSuccess('function(response) { alert('success') }')
 *     ->onError('function(err) { alert('error') }')
 *
 */
document.addEventListener('DOMContentLoaded', function () {
    $.fn.dataTable.ext.buttons.ajaxBatch = {
        name: 'ajaxBatch',
        extend: 'selected',
        className: 'buttons-ajax',
        text: 'Ajax Batch Action (Change Me)',
        action: function (e, dt, node, config) {
            let selected = dt.rows({selected: true}).data();
            let formData = { data: [] };
            for (let i = 0; i < selected.count(); i++) {
                formData.data.push(selected[i]);
            }

            if (config.hasOwnProperty('confirmation')) {
                if (! confirm(config.confirmation)) {
                    if (config.hasOwnProperty('onCancel')) config.onCancel();

                    return false;
                }
            }

            let url = config.url || '';
            let method = config.method || 'POST';

            $.ajax({
                url: url,
                method: method,
                data: formData
            }).done(response => {
                if (config.hasOwnProperty('onSuccess')) config.onSuccess(response);

                dt.draw();
            }).fail(err => {
                if (config.hasOwnProperty('onError')) config.onError(err);
            })
        }
    };
});
yajra

yajra commented on Nov 6, 2024

@yajra
Owner

A better approach would be like the below to pass the static analysis (phpstan):

  1. Create a reusable button
<?php

declare(strict_types=1);

namespace App\Editor\Buttons;

use Yajra\DataTables\Html\Button;

class BatchActionButton extends Button
{
    public function __construct(array $attributes = [])
    {
        $this->extend('ajaxBatch');

        parent::__construct($attributes);
    }

    public function url(string $url): static
    {
        $this->attributes['url'] = $url;

        return $this;
    }

    public function confirmation(string $confirmation): static
    {
        $this->attributes['confirmation'] = $confirmation;

        return $this;
    }

    public function onCancel(string $onCancel): static
    {
        $this->attributes['onCancel'] = $onCancel;

        return $this;
    }

    public function onSuccess(string $onSuccess): static
    {
        $this->attributes['onSuccess'] = $onSuccess;

        return $this;
    }

    public function onError(string $onError): static
    {
        $this->attributes['onError'] = $onError;

        return $this;
    }
}
  1. Use the custom button
            BatchActionButton::make()
                ->text('Restore')
                ->url(route('users.store'))
                ->confirmation('Generic confirmation message.')
                ->onCancel('function(response) { alert("confirmation cancelled") }')
                ->onSuccess('function(response) { alert("success") }')
                ->onError('function(err) { alert("error") }'),
Seb33300

Seb33300 commented on Nov 6, 2024

@Seb33300
ContributorAuthor

Thanks, I will take a look on this.

FYI, I also noticed that laravel-datatables-vite still has dependencies on Datatables v1:
https://github.com/yajra/laravel-datatables-vite/blob/51a126ec6020b7f3b97715e3e08af07c5be4f781/package.json#L33-L36

But from the documentation, we can read Datatables v2 is required:
https://yajrabox.com/docs/laravel-datatables/11.0#requirements

I had to load Datatables v2 by myself instead of importing laravel-datatables-vite as documented:
https://yajrabox.com/docs/laravel-datatables/11.0/quick-starter#datatables-with-vite

yajra

yajra commented on Nov 6, 2024

@yajra
Owner

DataTables v1 should work fine. You'll need v2 if you want to use the new layout function.

But yeah, the vite package should be updated to allow v2. Please feel free to submit a PR if possible. Thanks!

locked and limited conversation to collaborators on Dec 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Participants

      @Seb33300@yajra

      Issue actions

        Ajax batch action not working? · Issue #3190 · yajra/laravel-datatables