Basic use of asynchronous loading

{tip} The asynchronous loading feature supports load on demand of static resources, and currently all built-in all components support the use of asynchronous rendering in anywhere on the page.

The asynchronous loading feature allows for asynchronous rendering of whole or partial components of a page using ajax to improve page load efficiency (e.g. popups to load forms asynchronously).

Basic Usage

The following is a simple example to demonstrate the use of the asynchronous load feature

First, define an asynchronous rendering class that inherits Dcat\Admin\Support\LazyRenderable

  1. <?php
  2. namespace App\Admin\Renderable;
  3. use App\Admin\Widgets\Charts\Bar;
  4. use Dcat\Admin\Support\LazyRenderable;
  5. class PostChart extends LazyRenderable
  6. {
  7. public function render()
  8. {
  9. // Getting externally passed parameters
  10. $id = $this->id;
  11. // Query Data Logic
  12. $data = [...];
  13. // This can return built-in components, view files or HTML strings.
  14. return Bar::make($data);
  15. }
  16. }

Then you need to pass the rendering class instance into the Dcat\Admin\Widgets\Lazy object in order to achieve the final asynchronous rendering effect.

  1. use App\Admin\Renderable\PostChart;
  2. use Dcat\Admin\Widgets\Lazy;
  3. use Dcat\Admin\Layout\Content;
  4. public function index(Content $content)
  5. {
  6. // Instantiate asynchronous rendering classes and pass custom parameters
  7. $chart = PostChart::make(['id' => ...]);
  8. return $content->body(Lazy::make($chart));
  9. }

It can also be placed in the built-in components

{tip} In the case of components such as Dcat\Admin\Widgets\Card, Dcat\Admin\Widgets\Box, Dcat\Admin\Widgets\Modal, Dcat\Admin\Widgets\Tab, Dcat\Admin\Widgets\Tab may be omitted. Widgets\Lazy component, directly passing rendering class instances

  1. use App\Admin\Renderable\PostChart;
  2. use Dcat\Admin\Widgets\Card;
  3. use Dcat\Admin\Layout\Content;
  4. public function index(Content $content)
  5. {
  6. $chart = PostChart::make(['id' => ...]);
  7. // The Card component supports passing LazyRenderable instances directly, bypassing the Lazy object.
  8. return $content->body(Card::make($chart));
  9. }
  10. // In the case of Modal, Box, etc., you can just skip Lazy.
  11. use Dcat\Admin\Widgets\Modal;
  12. $chart = PostChart::make(['id' => ...]);
  13. $modal = Modal::make()
  14. ->lg()
  15. ->title('TITLE')
  16. ->delay(300) // If the chart is rendered asynchronously, you need to set a delay time, otherwise the chart may render abnormally.
  17. ->body($chart);

Of course, it can also be prevented in views or HTML code

  1. use App\Admin\Renderable\PostChart;
  2. use Dcat\Admin\Widgets\Lazy;
  3. use Dcat\Admin\Layout\Content;
  4. public function index(Content $content)
  5. {
  6. $chart = Lazy::make(PostChart::make(['id' => ...]));
  7. return $content->body(view('admin.xxx', ['chart' => $chart]));
  8. }

result

Basic use of asynchronous loading - 图1

Dcat\Admin\Support\LazyRenderable

parameter passing (payload)

  1. use App\Admin\Renderable\PostChart;
  2. PostChart::make(['key1' => '值', ...]);
  3. // Can also be passed via the payload method
  4. PostChart::make()->payload(['key1' => '值', ...]);

Get Parameters

  1. class PostChart extends LazyRenderable
  2. {
  3. protected $title = ['#', 'TITLE', '内容'];
  4. public function render()
  5. {
  6. // Getting externally passed parameters
  7. $key1 = $this->key1;
  8. $key2 = $this->key2;
  9. ...
  10. }
  11. }

Loading JS and CSS

The asynchronous load feature also supports static resources on demand and is very easy to use.

  1. <?php
  2. namespace App\Admin\Renderable;
  3. use Dcat\Admin\Support\LazyRenderable;
  4. use Dcat\Admin\Admin;
  5. class CustomView extends LazyRenderable
  6. {
  7. // Write the paths to the js and css files that need to be loaded here
  8. public static $js = [
  9. 'xxx/xxx1.js',
  10. 'xxx/xxx2.js',
  11. ];
  12. public static $css = [
  13. 'xxx/xxx1.css',
  14. 'xxx/xxx2.css',
  15. ];
  16. protected function addScript()
  17. {
  18. Admin::script(
  19. <<<JS
  20. console.log('The JS scripts are all loaded.~');
  21. JS
  22. );
  23. }
  24. public function render()
  25. {
  26. // Adding your JS code
  27. $this->addScript();
  28. return view('admin.custom', ['...']);
  29. }
  30. }

Template file code examples, be careful not to include tags such as body and html etc.

  1. <div id="custom" class="custom"><h2>asynchronous load function</h2></div>
  2. <script>
  3. Dcat.ready(function () {
  4. // JS The code can also be placed in the template file
  5. console.log('Template file execution js~');
  6. });
  7. </script>

Dcat\Admin\Widgets\Lazy

onLoad

This method allows you to listen for asynchronous load completion events

  1. use App\Admin\Renderable\PostChart;
  2. use Dcat\Admin\Widgets\Lazy;
  3. $chart = Lazy::make(PostChart::make())->onLoad(
  4. <<<JS
  5. console.log('Component rendering complete');
  6. JS
  7. );

load

This method controls whether to render the asynchronous component immediately.

  1. use App\Admin\Renderable\PostChart;
  2. use Dcat\Admin\Widgets\Lazy;
  3. use Dcat\Admin\Admin;
  4. $lazy = Lazy::make(PostChart::make())->load(false);
  5. Admin::script(
  6. <<<JS
  7. setTimeout(function () {
  8. // Asynchronous rendering event triggered automatically after 3 seconds
  9. {$lazy->getLoadScript()}
  10. }, 3000);
  11. JS
  12. );

JS events

  1. use App\Admin\Renderable\PostChart;
  2. use Dcat\Admin\Widgets\Lazy;
  3. use Dcat\Admin\Admin;
  4. $lazy = Lazy::make(PostChart::make());
  5. Admin::script(
  6. <<<JS
  7. // Manually triggering asynchronous rendering events
  8. $('{$lazy->getElementSelector()}').trigger('lazy:load');
  9. // Listening for rendering completion events
  10. $('{$lazy->getElementSelector()}').on('lazy:loaded', function () {
  11. console.log('The component is rendered.')
  12. });
  13. JS
  14. );

Loading data tables asynchronously

If you need to load the data table asynchronously, you need to inherit Dcat\Admin\Grid\LazyRenderable when defining the rendering class

  1. <?php
  2. namespace App\Admin\Renderable;
  3. use Dcat\Admin\Grid;
  4. use Dcat\Admin\Grid\LazyRenderable;
  5. use Dcat\Admin\Models\Administrator;
  6. class UserTable extends LazyRenderable
  7. {
  8. // Specify the name of the translation file
  9. protected $translation = 'user';
  10. public function grid(): Grid
  11. {
  12. return Grid::make(new Administrator(), function (Grid $grid) {
  13. $grid->column('id');
  14. $grid->column('username');
  15. $grid->column('name');
  16. $grid->column('created_at');
  17. $grid->column('updated_at');
  18. $grid->quickSearch(['id', 'username', 'name']);
  19. $grid->paginate(10);
  20. $grid->disableActions();
  21. $grid->filter(function (Grid\Filter $filter) {
  22. $filter->like('username')->width(4);
  23. $filter->like('name')->width(4);
  24. });
  25. });
  26. }
  27. }

Usage

  1. use App\Admin\Renderable\UserTable;
  2. use Dcat\Admin\Widgets\Modal;
  3. use Dcat\Admin\Layout\Content;
  4. public function index(Content $content)
  5. {
  6. $modal = Modal::make()
  7. ->lg()
  8. ->title('异步加载 - 表格')
  9. ->body(UserTable::make()) // Modal components support direct passing of rendering class instances.
  10. ->button('Open Form');
  11. return $content->body($modal);
  12. }

result

Basic use of asynchronous loading - 图2

Similarly, instances of the Render class can be attached to components such as Dcat\Admin\Widgets\Card, Dcat\Admin\Widgets\Box, Dcat\Admin\Widgets\Tab.

  1. use App\Admin\Renderable\UserTable;
  2. use Dcat\Admin\Widgets\Card;
  3. $table = UserTable::make();
  4. $card = Card::make('TITLE', $table)->withHeaderBorder();

When the above code renders the UserTable instance, it is actually an instance of the Dcat\Admin\Widgets\LazyTable class automatically added at the bottom level.

  1. use App\Admin\Renderable\UserTable;
  2. use Dcat\Admin\Widgets\Card;
  3. use Dcat\Admin\Widgets\LazyTable;
  4. $table = LazyTable::make(UserTable::make()->simple());
  5. $card = Card::make('TITLE', $table)->withHeaderBorder();

Dcat\Admin\Grid\LazyRenderable

Dcat\AdminGrid\LazyRenderable is used for asynchronous rendering of data tables and is a subclass of Dcat\AdminSupport\LazyRenderable

Simplified model

This feature removes the ability to simplify some data forms that are enabled by default and not enabled by default.

  1. use App\Admin\Renderable\UserTable;
  2. use Dcat\Admin\Widgets\LazyTable;
  3. use Dcat\Admin\Layout\Content;
  4. public function index(Content $content)
  5. {
  6. $table = UserTable::make()->simple();
  7. return $content->body(LazyTable::make($table));
  8. }

Note that if a rendering class instance is injected directly into a component such as Dcat\Admin\Widgets\Card, Dcat\Admin\Widgets\Box, Dcat\Admin\WidgetsTab and Dcat\Admin\WidgetsModal, Dcat\Admin\Widgets simple mode is automatically enabled.

  1. use App\Admin\Renderable\UserTable;
  2. use Dcat\Admin\Widgets\Card;
  3. // simple mode is automatically enabled here.
  4. $card = Card::make('TITLE', UserTable::make())->withHeaderBorder();

If you don’t want simple mode enabled, you can pass the LazyTable instance

  1. use App\Admin\Renderable\UserTable;
  2. use Dcat\Admin\Widgets\Card;
  3. use Dcat\Admin\Widgets\LazyTable;
  4. $table = LazyTable::make(UserTable::make());
  5. $card = Card::make('TITLE', $table)->withHeaderBorder();

Dcat\Admin\Widgets\LazyTable

onLoad

This method allows you to listen for asynchronous load completion events.

  1. use App\Admin\Renderable\PostChart;
  2. use Dcat\Admin\Widgets\Lazy;
  3. $chart = Lazy::make(PostChart::make())->onLoad(
  4. <<<JS
  5. console.log('Component rendering complete');
  6. JS
  7. );

load

This method controls whether to render the asynchronous component immediately. The default value is true.

  1. use App\Admin\Renderable\UserTable;
  2. use Dcat\Admin\Widgets\LazyTable;
  3. use Dcat\Admin\Admin;
  4. $lazy = LazyTable::make(UserTable::make())->load(false);
  5. Admin::script(
  6. <<<JS
  7. setTimeout(function () {
  8. // Asynchronous rendering event triggered automatically after 3 seconds
  9. {$lazy->getLoadScript()}
  10. }, 3000);
  11. JS
  12. );

JS events

  1. use App\Admin\Renderable\UserTable;
  2. use Dcat\Admin\Widgets\LazyTable;
  3. use Dcat\Admin\Admin;
  4. $lazy = LazyTable::make(UserTable::make());
  5. Admin::script(
  6. <<<JS
  7. // Manually triggering asynchronous rendering events
  8. $('{$lazy->getElementSelector()}').trigger('table:load');
  9. // Listening for rendering completion events
  10. $('{$lazy->getElementSelector()}').on('table:loaded', function () {
  11. console.log('The component is rendered.')
  12. });
  13. JS
  14. );

Asynchronous Loading Tool Form

Define the tool form class, implement the Dcat\Admin\Contracts\LazyRenderable, and load the trait of Dcat\Admin\Traits\LazyWidget.

  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. // Specify the name of the translation file
  10. protected $translation = 'user-profile';
  11. public function handle(array $input)
  12. {
  13. return $this->response()->success('Save successfully');
  14. }
  15. public function form()
  16. {
  17. $this->text('name', trans('admin.name'))->required()->help('User nickname');
  18. $this->image('avatar', trans('admin.avatar'))->autoUpload();
  19. $this->password('old_password', trans('admin.old_password'));
  20. $this->password('password', trans('admin.password'))
  21. ->minLength(5)
  22. ->maxLength(20)
  23. ->customFormat(function ($v) {
  24. if ($v == $this->password) {
  25. return;
  26. }
  27. return $v;
  28. })
  29. ->help('Please enter 5-20 characters');
  30. $this->password('password_confirmation', trans('admin.password_confirmation'))
  31. ->same('password')
  32. ->help('Please enter your confirmation password.');
  33. }
  34. }

use

  1. use App\Admin\Forms\UserProfile;
  2. use Dcat\Admin\Widgets\Modal;
  3. use Dcat\Admin\Layout\Content;
  4. public function index(Content $content)
  5. {
  6. $modal = Modal::make()
  7. ->lg()
  8. ->title('Asynchronous Loading - Forms')
  9. ->body(UserProfile::make()) // Modal components support direct passing of rendering class instances
  10. ->button('Open Form');
  11. return $content->body($modal);
  12. }

result

Basic use of asynchronous loading - 图3

Asynchronous form instances, of course, can be used in other components as well

  1. use App\Admin\Forms\UserProfile;
  2. use Dcat\Admin\Widgets\Lazy;
  3. use Dcat\Admin\Widgets\Card;
  4. $form = UserProfile::make();
  5. // Passing directly to Card Components
  6. $card = Card::make($form);
  7. // equal to
  8. $card = Card::make(Lazy::make($form));

Passing custom parameters

Passing parameters to an asynchronous form is very simple, modify the above form class as follows

  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. // Getting externally passed parameters
  12. $key1 = $this->payload['key1'] ?? null;
  13. $key2 = $this->payload['key1'] ?? null;
  14. return $this->response()->success('Save successfully');
  15. }
  16. public function form()
  17. {
  18. // Getting externally passed parameters
  19. $key1 = $this->payload['key1'] ?? null;
  20. $key2 = $this->payload['key1'] ?? null;
  21. $this->text('name', trans('admin.name'))->required()->help('User nickname');
  22. $this->image('avatar', trans('admin.avatar'))->autoUpload();
  23. $this->password('old_password', trans('admin.old_password'));
  24. $this->password('password', trans('admin.password'))
  25. ->minLength(5)
  26. ->maxLength(20)
  27. ->customFormat(function ($v) {
  28. if ($v == $this->password) {
  29. return;
  30. }
  31. return $v;
  32. })
  33. ->help('Please enter 5-20 characters');
  34. $this->password('password_confirmation', trans('admin.password_confirmation'))
  35. ->same('password')
  36. ->help('Please enter your confirmation password.');
  37. }
  38. public function default()
  39. {
  40. // Getting externally passed parameters
  41. $key1 = $this->payload['key1'] ?? null;
  42. $key2 = $this->payload['key1'] ?? null;
  43. return [
  44. 'name' => '...',
  45. ];
  46. }
  47. }

Passing parameter code as follows

  1. // Passing custom parameters
  2. $form = UserProfile::make()->payload(['key1' => '...', 'key2' => '...']);
  3. $modal = Modal::make()
  4. ->lg()
  5. ->title('Asynchronous Loading - Forms')
  6. ->body($form)
  7. ->button('Open Form');