Display and expansion of columns

The datagrid has a number of built-in methods for manipulating columns, which makes it very flexible to manipulate column data.

Display different components according to conditions

There are situations where we need to decide whether to use a display function of a column based on certain conditions.

{tip} Note that GridColumn::if is only valid for functions related to the display of columns, other methods such as operations related to table headers do not work with this method!

  1. $grid->column('config')
  2. ->if(function ($column) {
  3. // Gets the value of other fields in the current row
  4. $username = $this->username;
  5. // $column->getValue() is the value of the current field
  6. return $column->getValue();
  7. })
  8. ->display($view)
  9. ->copyable()
  10. ->else()
  11. ->display('');

The above is equivalent to

  1. $grid->column('config')
  2. ->if(function ($column) {
  3. return $column->getValue();
  4. })
  5. ->then(function (Grid\Column $column) {
  6. $column->display($view)->copyable();
  7. })
  8. ->else(function (Grid\Column $column) {
  9. $column->display('');
  10. });

Support for multiple ifs

  1. $grid->column('config')
  2. ->if(...)
  3. ->then(...)
  4. ->else(...)
  5. ->if(...)
  6. ->then(...)
  7. ->else(...);

End condition judgments end

  1. $grid->column('status')
  2. ->if(...) // Condition 1
  3. ->display(...)
  4. ->display(...)
  5. ->if(...) // condition 2
  6. ->display(...)
  7. ->display(...)
  8. ->end() // end the previous condition
  9. ->display(...) ; // All conditions are valid

Column display

model-grid has several built-in methods to help you extend the column functionality

display

The Dcat\Admin\Grid\Column object has a built-in display() method to handle the current value via an incoming callback function

  1. $grid->column('title')->display(function ($title) {
  2. return "<span style='color:blue'>$title</span>";
  3. });

The data can be manipulated in any way in the incoming anonymous function, and in addition the anonymous function binds the data of the current row as a parent object that can be called in the function:

  1. $grid->column('first_name');
  2. $grid->column('last_name');
  3. // Non-existent `full_name` field
  4. $grid->column('full_name')->display(function () {
  5. return $this->first_name . ' ' . $this->last_name;
  6. });

Set the HTML properties of the column

Set the html attribute of the column

  1. $grid->column('name')->setAttributes(['style' => 'font-size:14px']);

Column view

The view method can introduce a view file

  1. $grid->column('content')->view('admin.fields.content');

Three variables are passed into the view by default:

  • $model current row data
  • $name field name
  • $value is the current value.

The template code is as follows:

  1. <label>name:{{ $name }}</label>
  2. <label>value:{{ $value }}</label>
  3. <label>other fields:{{ $model->title }}</label>

Pictures

  1. $grid->column('picture')->image();
  2. //Setting up servers and width and height
  3. $grid->column('picture')->image('http://xxx.com', 100, 100);
  4. // Show multiple pictures
  5. $grid->column('pictures')->display(function ($pictures) {
  6. return json_decode($pictures, true);
  7. })->image('http://xxx.com', 100, 100);

show label label

Supports all the colors built into the Dcat\Admin\Color class

  1. use Dcat\Admin\Admin;
  2. $grid->column('name')->label();
  3. // Set color, pass alias directly.
  4. $grid->column('name')->label('danger');
  5. // It can also be used like this
  6. $grid->column('name')->label(Admin::color()->danger());
  7. // You can also pass the color code directly.
  8. $grid->column('name')->label('#222');

Set different colors for different values

  1. use Dcat\Admin\Admin;
  2. $grid->column('state')->using([1 => 'unprocessed', 2 => 'processed', ...])->label([
  3. 'default' => 'primary', // Set the default color, or default if not set.
  4. 1 => 'primary',
  5. 2 => 'danger',
  6. 3 => 'success',
  7. 4 => Admin::color()->info(),
  8. ]);

Displaying badge tags

Supports all the colors built into the Dcat\Admin\Color class.

  1. $grid->column('name')->badge();
  2. // Set color, pass alias directly.
  3. $grid->column('name')->badge('danger');
  4. // It can also be used like this
  5. $grid->column('name')->badge(Admin::color()->danger());
  6. // You can also pass the color code directly
  7. $grid->column('name')->badge('#222');

Set different colors for different values

  1. use Dcat\Admin\Admin;
  2. $grid->state->using([1 => 'unprocessed', 2 => 'processed', ...])->badge([
  3. 'default' => 'primary', // Set the default color, or default if not set.
  4. 1 => 'primary',
  5. 2 => 'danger',
  6. 3 => 'success',
  7. 4 => Admin::color()->info(),
  8. ]);

Boolean display (bool)

This column is shown as and after converting it to a bool value

  1. $grid->column('approved')->bool();

You can also specify the display according to the value of this column, for example, fields with values Y and N indicate true and false.

  1. $grid->column('approved')->bool(['Y' => true, 'N' => false]);

result Display and expansion of columns - 图1

Dot prefix (dot)

Column text can be preceded by a colored dot using the dot method

  1. use Dcat\Admin\Admin;
  2. $grid->column('state')
  3. ->using([1 => 'unprocessed', 2 => 'processed', ...])
  4. ->dot(
  5. [
  6. 1 => 'primary',
  7. 2 => 'danger',
  8. 3 => 'success',
  9. 4 => Admin::color()->info(),
  10. ],
  11. 'primary' // The second parameter is the default value.
  12. );

result Display and expansion of columns - 图2

Column expansion (expand)

The expand method hides the content and displays it on the next line of the table when the button is clicked.

  1. $grid->column('content')
  2. ->display('details') // Set the button name
  3. ->expand(function () {
  4. // Return the displayed details
  5. // This returns the contents of the content field and wraps it with a card.
  6. $card = new Card(null, $this->content);
  7. return "<div style='padding:10px 10px 0'>$card</div>";
  8. });

Buttons can also be set in the following ways

  1. $grid->column('content')->expand(function (Grid\Displayers\Expand $expand) {
  2. // Set the button name
  3. $expand->button('details');
  4. // Return the displayed details
  5. // This returns the contents of the content field and wraps it with a card.
  6. $card = new Card(null, $this->content);
  7. return "<div style='padding:10px 10px 0'>$card</div>";
  8. });

asynchronous loading

{tip} For further information, please refer to the document asynchronous loading

Define rendering classes that inherit Dcat\Admin\Support\LazyRenderable

  1. use App\Models\Post as PostModel;
  2. use Dcat\Admin\Support\LazyRenderable;
  3. use Dcat\Admin\Widgets\Table;
  4. class Post extends LazyRenderable
  5. {
  6. public function render()
  7. {
  8. // Get ID
  9. $id = $this->key;
  10. // Get other custom parameters
  11. $type = $this->post_type;
  12. $data = PostModel::where('user_id', $id)
  13. ->where('type', $type)
  14. ->get(['title', 'body', 'body', 'created_at'])
  15. ->toArray();
  16. $titles = [
  17. 'User ID',
  18. 'Title',
  19. 'Body',
  20. 'Created At',
  21. ];
  22. return Table::make($titles, $data);
  23. }
  24. }

use

  1. $grid->post->display('View')->expand(Post::make(['post_type' => 1]));
  2. // Instances of asynchronously loaded classes can be returned within closures
  3. $grid->post->expand(function () {
  4. // Allows return of asynchronously loaded class instances within than package
  5. return Post::make(['title' => $this->title]);
  6. });

result

Display and expansion of columns - 图3

Asynchronous Loading Tool Form

Define the tools-form class as follows

{tip} See asynchronous loading for more information on how to use it.

  1. <?php
  2. namespace App\Admin\Forms;
  3. use Dcat\Admin\Contracts\LazyRenderable;
  4. use Dcat\Admin\Traits\LazyWidget;
  5. use Dcat\Admin\Widgets\Form;
  6. class UserProfile extends Form implements LazyRenderable
  7. {
  8. use LazyWidget;
  9. public function handle(array $input)
  10. {
  11. // Receive externally passed parameters
  12. $type = $this->payload['type'] ?? null;
  13. return $this->response()->success('Save success');
  14. }
  15. public function form()
  16. {
  17. // Receive externally passed parameters
  18. $type = $this->payload['type'] ?? null;
  19. $this->text('name', trans('admin.name'))->required()->help('Nickname');
  20. $this->image('avatar', trans('admin.avatar'))->autoUpload();
  21. $this->password('old_password', trans('admin.old_password'));
  22. $this->password('password', trans('admin.password'))
  23. ->minLength(5)
  24. ->maxLength(20)
  25. ->customFormat(function ($v) {
  26. if ($v == $this->password) {
  27. return;
  28. }
  29. return $v;
  30. })
  31. ->help('Please enter 5-20 characters');
  32. $this->password('password_confirmation', trans('admin.password_confirmation'))
  33. ->same('password')
  34. ->help('Please confirm your password.');
  35. }
  36. }

use

  1. $grid->user->display('View')->expand(UserProfile::make(['type' => 1]));

Pop-up modal box (modal)

The modal method hides the content and displays it on the next line of the table when the button is clicked.

  1. $grid->column('content')
  2. ->display('See') // Set the button name
  3. ->modal(function ($modal) {
  4. // Set pop-up window TITLE
  5. $modal->title('TITLE '.$this->username);
  6. // Custom icons
  7. $modal->icon('feather icon-x');
  8. $card = new Card(null, $this->content);
  9. return "<div style='padding:10px 10px 0'>$card</div>";
  10. });
  11. // You can also set the pop-up TITLE in this way
  12. $grid->column('content')
  13. ->display('see') // Set the button name
  14. ->modal('Pop-up window TITLE', ...);

asynchronous loading

{tip} For more specific usage of asynchronous loading, please refer to the document Asynchronous Loading.

Define rendering classes that inherit Dcat\Admin\Support\LazyRenderable

  1. use App\Models\Post as PostModel;
  2. use Dcat\Admin\Support\LazyRenderable;
  3. use Dcat\Admin\Widgets\Table;
  4. class Post extends LazyRenderable
  5. {
  6. public function render()
  7. {
  8. // Get ID
  9. $id = $this->key;
  10. // Get other custom parameters
  11. $type = $this->post_type;
  12. $data = PostModel::where('user_id', $id)
  13. ->where('type', $type)
  14. ->get(['title', 'body', 'body', 'created_at'])
  15. ->toArray();
  16. $titles = [
  17. 'User ID',
  18. 'Title',
  19. 'Body',
  20. 'Created At',
  21. ];
  22. return Table::make($titles, $data);
  23. }
  24. }

use

  1. $grid->post->display('View')->modal('Post', Post::make(['post_type' => 2]));
  2. // Instances of asynchronously loaded classes can be returned within closures
  3. $grid->post->modal(function ($modal) {
  4. $modal->title('Custom pop-up window TITLE');
  5. // Allows return of asynchronously loaded class instances within than package
  6. return Post::make(['title' => $this->title]);
  7. });

result Display and expansion of columns - 图4

Asynchronous Loading Tool Form

Define the tools-form class as follows

{tip} See asynchronous loading for more information on how to use it.

  1. <?php
  2. namespace App\Admin\Forms;
  3. use Dcat\Admin\Contracts\LazyRenderable;
  4. use Dcat\Admin\Traits\LazyWidget;
  5. use Dcat\Admin\Widgets\Form;
  6. class UserProfile extends Form implements LazyRenderable
  7. {
  8. use LazyWidget;
  9. public function handle(array $input)
  10. {
  11. // Receive externally passed parameters
  12. $type = $this->payload['type'] ?? null;
  13. return $this->response()->success('Save success');
  14. }
  15. public function form()
  16. {
  17. // Receive externally passed parameters
  18. $type = $this->payload['type'] ?? null;
  19. $this->text('name', trans('admin.name'))->required()->help('User nickname');
  20. $this->image('avatar', trans('admin.avatar'))->autoUpload();
  21. $this->password('old_password', trans('admin.old_password'));
  22. $this->password('password', trans('admin.password'))
  23. ->minLength(5)
  24. ->maxLength(20)
  25. ->customFormat(function ($v) {
  26. if ($v == $this->password) {
  27. return;
  28. }
  29. return $v;
  30. })
  31. ->help('Please enter 5-20 characters');
  32. $this->password('password_confirmation', trans('admin.password_confirmation'))
  33. ->same('password')
  34. ->help('Please confirm your password.');
  35. }
  36. }

use

  1. $grid->user->display('View')->modal(UserProfile::make(['type' => 1]));

Progress Bar

progressBar progress bar

  1. $grid->rate->progressBar();
  2. //Set the color, default `primary`, optional `danger`, `warning`, `info`, `primary`, `success`.
  3. $grid->rate->progressBar('success');
  4. // Set progress bar size and maximum value
  5. $grid->rate->progressBar('success', 'sm', 100);

showTreeInDialog

The showTreeInDialog method can present an array with hierarchies as a tree popup, such as permissions

  1. // Find out all the permissions data
  2. $nodes = (new $permissionModel)->allNodes();
  3. // Passing a two-dimensional array (not hierarchical)
  4. $grid->permissions->showTreeInDialog($nodes);
  5. // You can also pass in closures.
  6. $grid->permissions->showTreeInDialog(function (Grid\Displayers\DialogTree $tree) use (&$nodes, $roleModel) {
  7. // Set all nodes
  8. $tree->nodes($nodes);
  9. // Set the node data field name, default "id", "name", "parent_id"
  10. $tree->setIdColumn('id');
  11. $tree->setTitleColumn('title');
  12. $tree->setParentColumn('parent_id');
  13. // $this->roles can get the value of the current row's field.
  14. foreach (array_column($this->roles, 'slug') as $slug) {
  15. if ($roleModel::isAdministrator($slug)) {
  16. // Select all nodes
  17. $tree->checkAll();
  18. }
  19. }
  20. });

Display and expansion of columns - 图5

Content mapping (using)

  1. $grid->status->using([0 => '未激活', 1 => '正常']);
  2. // The second parameter is the default value
  3. $grid->gender->using([1 => '男', 2 => '女'], '未知');

String split into arrays

The explode method splits the string into arrays.

  1. $grid->tag->explode()->label();
  2. // You can specify delimiter, default ",".
  3. $grid->tag->explode('|')->label();

prepend

The prepend method is used to insert content in front of a value of type string or array

  1. // When the value of a field is a string
  2. $grid->email->prepend('mailto:');
  3. // When the value of a field is an array
  4. $grid->arr->prepend('first item');

The prepend method allows passing parameters to closures

  1. $grid->email->prepend(function ($value, $original) {
  2. // $value is the current field value
  3. // $original is the original value of the current field as queried from the database.
  4. // Get other field values
  5. $username = $this->username;
  6. return "[{$username}]";
  7. });

append

The append method is used to insert content after a value of type string or array.

  1. // When the value of a field is a string
  2. $grid->email->append('@gmail.com');
  3. // When the value of a field is an array
  4. $grid->arr->append('last item');

The append method allows passing parameters to closures

  1. $grid->email->prepend(function ($value, $original) {
  2. // $value is the current field value
  3. // $original is the original value of the current field as queried from the database.
  4. // Get other field values
  5. $username = $this->username;
  6. return "[{$username}]";
  7. });

String or array capture (limit)

  1. // Display up to 50 characters.
  2. $grid->column('content')->limit(50, '...');
  3. // Also supported if the field value is an array.
  4. $grid->tags->limit(3);

Column QR code (qrcode)

  1. $grid->website->qrcode(function () {
  2. return $this->url;
  3. }, 200, 200);

Copyable (copyable)

  1. $grid->website->copyable();

orderable (orderable)

Field sortability can be enabled via Column::orderable, which requires use ModelTree or use SortableTrait in your model class, and needs to inherit the Spatie\EloquentSortable\Sortable interface.

SortableTrait

If your data is not hierarchically structured data, you can just use use SortableTrait, see eloquent-sortable for more usage.

model

  1. <?php
  2. namespace App\Models;
  3. use Illuminate\Database\Eloquent\Model;
  4. use Spatie\EloquentSortable\Sortable;
  5. use Spatie\EloquentSortable\SortableTrait;
  6. class MyModel extends Model implements Sortable
  7. {
  8. use SortableTrait;
  9. protected $sortable = [
  10. // Set the sort field name
  11. 'order_column_name' => 'order',
  12. // If or not to sort automatically on creation, this parameter is recommended to be set to true.
  13. 'sort_when_creating' => true,
  14. ];
  15. }

use

  1. $grid->model()->orderBy('order');
  2. $grid->order->orderable();

ModelTree

If your data is hierarchical, you can simply use use Model, here is an example of permission model to demonstrate usage

{tip} ModelTree actually inherits the functionality of eloquent-sortable as well.

  1. <?php
  2. namespace Dcat\Admin\Models;
  3. use Dcat\Admin\Traits\HasDateTimeFormatter;
  4. use Dcat\Admin\Traits\ModelTree;
  5. use Spatie\EloquentSortable\Sortable;
  6. class Permission extends Model implements Sortable
  7. {
  8. use HasDateTimeFormatter,
  9. ModelTree {
  10. ModelTree::boot as treeBoot;
  11. }
  12. ...
  13. }

use

  1. $grid->order->orderable();

Link (link)

Display the field as a link

  1. // When the link method does not pass parameters, the link's `href` and `text` are the current values
  2. $grid->column('homepage')->link();
  3. // incoming closure
  4. $grid->column('homepage')->link(function ($value) {
  5. return admin_url('users/'.$value);
  6. });

row actions (action)

{tip} Before using this method, please read custom-actions-row-actions.

This function displays a column as a button for a row operation, such as the following, which shows a marked and unmarked column operation. After clicking the asterisk icon in this column, the background will switch the state of the field and the page icon will follow. The specific implementation code is as follows:

  1. <?php
  2. namespace App\Admin\Extensions\Grid\RowAction;
  3. use Dcat\Admin\Grid\RowAction;
  4. use Illuminate\Http\Request;
  5. class Star extends RowAction
  6. {
  7. protected function html()
  8. {
  9. $icon = ($this->row->{$this->getColumnName()}) ? 'fa-star' : 'fa-star-o';
  10. return <<<HTML
  11. <i class="{$this->getElementClass()} fa {$icon}"></i>
  12. HTML;
  13. }
  14. public function handle(Request $request)
  15. {
  16. try {
  17. $class = $request->class;
  18. $column = $request->column;
  19. $id = $this->getKey();
  20. $model = $class::find($id);
  21. $model->{$column} = (int) !$model->{$column};
  22. $model->save();
  23. return $this->response()->success("success")->refresh();
  24. } catch (\Exception $e) {
  25. return $this->response()->error($e->getMessage());
  26. }
  27. }
  28. public function parameters()
  29. {
  30. return [
  31. 'class' => $this->modelClass(),
  32. 'column' => $this->getColumnName(),
  33. ];
  34. }
  35. public function getColumnName()
  36. {
  37. return $this->column->getName();
  38. }
  39. public function modelClass()
  40. {
  41. return get_class($this->parent->model()->repository()->model());
  42. }
  43. }

use

  1. protected function grid()
  2. {
  3. $grid = new Grid(new $this->model());
  4. $grid->column('star', '-')->action(Star::class); // here
  5. $grid->column('id', 'ID')->sortable()->bold();
  6. return $grid;
  7. }

result

Display and expansion of columns - 图6

Ways to help

String manipulation

If the current output data is a string, the method of Illuminate\Support\Str can be called by chaining methods.

For example, there is a column that displays the string value of the title field as follows:

  1. $grid->title();

Call the Str::title() method on top of the output string in the title column

  1. $grid->title()->title();

After calling the method, the output is still a string, so you can continue to call the Illuminate\Support\Str method:

  1. $grid->title()->title()->ucfirst();
  2. $grid->title()->title()->ucfirst()->substr(1, 10);

Array manipulation

You can directly chain call the Illuminate\Support\Collection method if the output from the front is an array.

For example, the tags column is an array of data retrieved from a one-to-many relationship:

  1. $grid->tags();
  2. array (
  3. 0 =>
  4. array (
  5. 'id' => '16',
  6. 'name' => 'php',
  7. 'created_at' => '2016-11-13 14:03:03',
  8. 'updated_at' => '2016-12-25 04:29:35',
  9. ),
  10. 1 =>
  11. array (
  12. 'id' => '17',
  13. 'name' => 'python',
  14. 'created_at' => '2016-11-13 14:03:09',
  15. 'updated_at' => '2016-12-25 04:30:27',
  16. ),
  17. )

Call the Collection::puck() method to retrieve the name column from the array

  1. $grid->tags()->pluck('name');
  2. array (
  3. 0 => 'php',
  4. 1 => 'python',
  5. ),

After the name column is extracted, the output is still an array, and the method of Illuminate\Support\Collection can still be called

  1. $grid->tags()->pluck('name')->map('ucwords');
  2. array (
  3. 0 => 'Php',
  4. 1 => 'Python',
  5. ),

Output an array as a string

  1. $grid->tags()->pluck('name')->map('ucwords')->implode('-');

Result:

  1. "Php-Python"

Mixed use

In the above two types of method calls, as long as the output from the previous step is a value of a definite type, the method corresponding to the type can be called, so it can be used flexibly in combination.

For example, the images field is a JSON-format string type that stores an array of multiple image addresses:

  1. $grid->images();
  2. // "['foo.jpg', 'bar.png']"
  3. // Chained method calls to display multiple graphs
  4. $grid->images()->display(function ($images) {
  5. return json_decode($images, true);
  6. })->map(function ($path) {
  7. return 'http://localhost/images/'. $path;
  8. })->image();

Expanding the display of columns

The column functionality can be extended in two ways, the first being through anonymous functions.

The IDE will not auto-complete after the expanded column method, so you can generate an IDE hint file with php artisan admin: ide-helper.

anonymous function

Add the following code to app/Admin/bootstrap.php:

  1. use Dcat\Admin\Grid\Column;
  2. // The second parameter is a custom parameter
  3. Column::extend('color', function ($value, $color) {
  4. return "<span style='color: $color'>$value</span>";
  5. });

Then use this extension in model-grid:

  1. $grid->title()->color('#ccc');

Extensions

If the column display logic is complex, it can be implemented by extending the class.

extension class app/Admin/Extensions/Popover.php:

  1. <?php
  2. namespace App\Admin\Extensions;
  3. use Dcat\Admin\Admin;
  4. use Dcat\Admin\Grid\Displayers\AbstractDisplayer;
  5. class Popover extends AbstractDisplayer
  6. {
  7. public function display($placement = 'left')
  8. {
  9. Admin::script("$('[data-toggle=\"popover\"]').popover()");
  10. return <<<EOT
  11. <button type="button"
  12. class="btn btn-secondary"
  13. title="popover"
  14. data-container="body"
  15. data-toggle="popover"
  16. data-placement="$placement"
  17. data-content="{$this->value}"
  18. >
  19. pop-up
  20. </button>
  21. EOT;
  22. }
  23. }

Then register the extension class in app/Admin/bootstrap.php:

  1. use Dcat\Admin\Grid\Column;
  2. use App\Admin\Extensions\Popover;
  3. Column::extend('popover', Popover::class);

Then it can be used in model-grid:

  1. $grid->desciption()->popover('right');

Specify the listing

In addition to the above two ways of extending the column functionality, we can also extend the column functionality by specifying the column name

Add the following code to app/Admin/bootstrap.php:

  1. use Dcat\Admin\Grid\Column;
  2. // This extension method is equivalent to the
  3. // $grid->title()->display(function ($value) {
  4. // return "<span style='color:red'>$value</span>"
  5. // });
  6. Column::define('title', function ($value) {
  7. return "<span style='color:red'>$value</span>"
  8. });
  9. // This extension method is equivalent to the
  10. // $grid->status()->switch();
  11. Column::define('status', Dcat\Admin\Grid\Displayers\SwitchDisplay::class);

The above extensions are then automatically used in the title and status fields in model-grid:

  1. $grid->title();
  2. $grid->status();