# Custom Actions

`row actions` and `batch action` of the data grid, and the row actions of the data are reconstructed into drop-down menu actions:

In this form, it is more convenient to extend the row action. The mechanism after refactoring can make you more elegant and custom data actions.

By default, the data table has 3 row actions `Edit`, `View` and `Delete` and a `Batch Delete` action. Refer to the following to customize your data action.

## Row action

Suppose you want to add a `copy` action to the article list. After clicking and copying the data of this line, run the following command to generate the action class:

```
Php artisan admin:action Post\\Replicate --grid-row --name="copy"
```

> The class name is specified as `Post\\Replicate`, just to put this action class under the `Post` namespace, you can specify any space according to your module.

The above command will generate the class file `app/Admin/Actions/Post/Replicate.php`:

```php
<?php

namespace App\Admin\Actions\Post;

use Ezadev\Admin\Actions\RowAction;
use Illuminate\Database\Eloquent\Model;

class Replicate extends RowAction
{
    public $name = 'copy';

    public function handle(Model $model)
    {
        // $model ...

        return $this->response()->success('Success message.')->refresh();
    }
}
```

The commit of the action will handle by the `handle` method in the class, so we only need to simply modify the logic of the `handle` method:

```php
    public function handle(Model $model)
    {
        // Here the model's `replicate` method is called to copy the data, then call the `save` method to save it.
        $model->replicate()->save();

        // return a success message with the content "copy success" and refresh the page
        return $this->response()->success('copy success.')->refresh();
    }
```

The first parameter `$model` of the `handle` method is the Eloquent model of the current row data, which can be manipulated directly.

The final step is to add to the grid:

```php
use App\Admin\Actions\Post\Replicate;

$grid->actions(function ($actions) {
    $actions->add(new Replicate);
});
```

### Page redirection

If your `row action` just click to jump to another page:

```php
<?php

namespace Ezadev\Admin\Grid\Actions;

use Ezadev\Admin\Actions\RowAction;

class Comments extends RowAction
{
    public $name = 'View comments';

    /**
     * @return string
     */
    public function href()
    {
        return "/your/uri/path";
    }
}
```

In the `href` method, you can use `$this->getResource()` to get the current resource root path. You can use `$this->getKey()` to get the primary key value of the current row.

## Batch action

Suppose you want to add a `batch copy` action, first run the following command to generate a batch action class:

```
Php artisan admin:action Post\\BatchReplicate --grid-batch --name="batch copy"
```

Generate the class file `app/Admin/Actions/Post/BatchReplicate.php`:

```php
<?php

namespace App\Admin\Actions\Post;

use Ezadev\Admin\Actions\BatchAction;
use Illuminate\Database\Eloquent\Collection;

class BatchReplicate extends BatchAction
{
    public $name = 'batch copy';

    public function handle(Collection $collection)
    {
        foreach ($collection as $model) {
            // ...
        }

        return $this->response()->success('Success message...')->refresh();
    }
}
```

Similarly, we only need to simply modify the logic of the `handle` method:

```php
    public function handle(Collection $collection)
    {
        // copy the data model for each row
        foreach ($collection as $model) {
            $model->replicate()->save();
        }

        / / return a success message of "copy success" and refresh the page
        return $this->response()->success('copy success.')->refresh();
    }
```

Add to the batch action:

```php
$grid->batchActions(function ($batch) {
    $batch->add(new BatchReplicate());
});
```

Then select a few rows of data in the list, click on it to see the new `batch copy`:

## Interaction

When you click on an action, you will often need to make some confirmations or fill in additional data. There are two ways to interact:

### pop-up dialogue box

For example, the above copy action, after clicking, you need to pop up a dialog box to confirm the action, add a dialog method to the class:

```php
    public function dialog()
    {
        $this->confirm('Are you sure to copy this row?');
    }
```

In this way, after clicking Copy, the following confirmation box will pop up, and the action will be submitted after confirmation.

### Popup form

Suppose that the 'topic list' has a report action. After clicking, you need to pop up a form, fill in the type and reason of the report, and refer to the following method:

Add the following code to the action class:

```php
public function form()
{
    $type = [
        1 => 'Advertising',
        2 => 'Illegal',
        3 => 'Fishing',
    ];

    $this->checkbox('type', 'type')->options($type);
    $this->textarea('reason', 'reason')->rules('required');
}
```

When the action is clicked, a `form` form pops up:

In the `handle` method, we need to add a second parameter to get the form value:

```php
use Illuminate\Http\Request;

public function handle(Model $model, Request $request)
{
    // Get the `type` value in the form
    $request->get('type');

    / / Get the `reason` value in the form
    $request->get('reason');

    // Your reporting logic...

    return $this->response()->success('Report submitted]'->refresh();
}
```

The current method support for the form reference:

```php
public function form()
{
    // text input box
    $this->text('name', 'Placeholder...')->rules('required|min:10');

    // Email input box
    $this->email('name', 'Placeholder...');

    // IP input box
    $this->ip('name', 'Placeholder...');

    // URL input box
    $this->url('name', 'Placeholder...');

    // password input box
    $this->password('name', 'Placeholder...');

    // mobile phone number input box
    $this->mobile('name', 'Placeholder...');

    // text field input box
    $this->textarea('name', 'Placeholder...');

    // Single box
    $this->select('name', 'Placeholder...')->options([]);

    // Checkbox
    $this->multipleSelect('name', 'Placeholder...')->options([]);

    // Checkbox
    $this->checkbox('name', 'Placeholder...')->options([]);

    // Radio
    $this->radio('name', 'Placeholder...')->options([]);

    // upload files
    $this->file('name', 'Placeholder...');

    // upload image
    $this->image('name', 'Placeholder...');

    // time and date selection
    $this->datetime('name', 'Placeholder...');

    // date selection
    $this->date('name', 'Placeholder...');

    // time selection
    $this->time('name', 'Placeholder...');

    // hide
    $this->hidden('name');
}
```

## Grid Tools

Custom actions, in addition to being displayed in the action column of the data table and in the drop-down menu of the batch action, can also be displayed in the tool area of ​​the table (Filter button line)

### Batch action

If you want to put the button for the batch action in the tool area instead of the drop-down menu for the batch action, you need to make some changes to the action class:

```php
<?php

namespace App\Admin\Actions\Post;

use Ezadev\Admin\Actions\BatchAction;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Http\Request;

class ReportPost extends BatchAction
{
    protected $selector = '.report-posts';

    public function handle(Collection $collection, Request $request)
    {
        foreach ($collection as $model) {
            //
        }

        return $this->response()->success('Report submitted!')->refresh();
    }

    public function form()
    {
        $this->checkbox('type', 'type')->options([]);
        $this->textarea('reason', 'reason')->rules('required');
    }

    public function html()
    {
        return "<a class='report-posts btn btn-sm btn-danger'><i class='fa fa-info-circle'></i>Report</a>";
    }
}
```

The value of `$selector` corresponds to the button CSS selector in the `html` method. Click the 'Report' button to submit the action.

Then add it to the toolbar of the form:

```php
$grid->tools(function (Grid\Tools $tools) {
    $tools->append(new ReportPost());
});
```

### Normal action

Suppose you need to add an 'Import Data\` button to the header of the form. After clicking, pop up the form upload file to import the data. Refer to the steps below.

Create a normal action class by running the following command:

```
Php artisan admin:action Post\\ImportPost --name="import data"
```

The generated class file `app/Admin/Actions/Post/ImportPost.php`:

```php
<?php

namespace App\Admin\Actions\Post;

use Ezadev\Admin\Actions\Action;
use Illuminate\Http\Request;

class ImportPost extends Action
{
    protected $selector = '.import-post';

    public function handle(Request $request)
    {
        // $request ...

        return $this->response()->success('Success message...')->refresh();
    }

    public function html()
    {
        return <<<HTML
        <a class="btn btn-sm btn-default import-post">Import data</a>
HTML;
    }
}
```

Modify this class to provide the ability to upload files and add logic to process the data:

```php
<?php

namespace App\Admin\Actions\Post;

use Ezadev\Admin\Actions\Action;
use Illuminate\Http\Request;

class ImportPost extends Action
{
    public $name = 'import data';

    protected $selector = '.import-post';

    public function handle(Request $request)
    {
        // The following code gets the uploaded file, then uses the package `maatwebsite/excel` to process and upload your file and save it to the database.
        $request->file('file');

        return $this->response()->success('Import complete!')->refresh();
    }

    public function form()
    {
        $this->file('file', 'Please select file');
    }

    public function html()
    {
        return <<<HTML
        <a class="btn btn-sm btn-default import-post"><i class="fa fa-upload"></i>Import data</a>
HTML;
    }
}
```

## Response

Here's an example of the simplest return:

```php
return $this->response()->success('Success!');
```

After the action class is processed, return a \`Success! The success of \`\`s tips, here are a few other types of returns:

```php
/ / Handling errors
Try {
    // Processing logic...

    return $this->response()->success('success...');
} catch (Exception $e) {
    return $this->response()->error('generating error: '.$e->getMessage());
}

// return prompt message
return $this->response()->info('prompt information...');

// return warning message
return $this->response()->warning('warning information...');
```

Refresh the page after returning:

```php
return $this->response()->success('Success!')->refresh();
```

Redirect to other pages after returning:

```php
return $this->response()->success('Success!')->redirect('/admin/users');
```

Download the file after returning:

```php
return $this->response()->success('Success!')->download('http://www.xxx.com/file.zip');
```
