Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ajax batch action not working? #3190

Open
Seb33300 opened this issue Nov 6, 2024 · 4 comments
Open

Ajax batch action not working? #3190

Seb33300 opened this issue Nov 6, 2024 · 4 comments

Comments

@Seb33300
Copy link

Seb33300 commented Nov 6, 2024

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?

@Seb33300 Seb33300 changed the title Batch action not working? Ajax batch action not working? Nov 6, 2024
@yajra
Copy link
Owner

yajra commented Nov 6, 2024

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
Copy link
Owner

yajra commented Nov 6, 2024

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
Copy link
Author

Seb33300 commented Nov 6, 2024

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
Copy link
Owner

yajra commented Nov 6, 2024

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!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants