# Panel dialogs

****

As part of your <a href="https://getkirby.com/docs/reference/plugins/extensions/panel-areas">Panel area extension</a>, you can also define custom dialogs for the Panel as well as extend or modify the Panel's default dialogs.

## Supported UI components

All reuse the same dialog components:

| Component name | Usage |
| --- | --- |
| <a href="https://lab.getkirby.com/public/lab/docs/k-error-dialog">`k-error-dialog`</a> | For detailed error warnings (i.e. form validation) |
| <a href="https://lab.getkirby.com/public/lab/docs/k-form-dialog">`k-form-dialog`</a> | For dialogs with form fields and submit buttons |
| <a href="https://lab.getkirby.com/public/lab/docs/k-remove-dialog">`k-remove-dialog`</a> | To confirm deleting items |
| <a href="https://lab.getkirby.com/public/lab/docs/k-text-dialog">`k-text-dialog`</a> | For dialogs with a custom text message |

## Dialog definition

Dialogs are defined as a part of areas:

```php
Kirby::plugin('yourname/todos', [
  'areas' => [
    'todos' => function ($kirby) {
      return [
        // ... other code for custom Panel area
        'dialogs' => [

          // the key of the dialog defines its routing pattern
          'todos/create' => [
            // dialog callback functions
            'load'   => function () {},
            'submit' => function () {}
          ]
        ]
      ];
    }
  ]
]);
```

### `load` callback

The `load` function is called when the dialog is opened. It needs to return an array that specifies the UI component (see above) to be used for the dialog as well as all props that should be passed to the UI component, e.g. field definitions and values for a form dialog.

```php
Kirby::plugin('yourname/todos', [
  'areas' => [
    'todos' => function ($kirby) {
      return [
        'dialogs' => [
          'todos/create' => [
            // the load event is creating a GET route at
            // `/panel/dialogs/{pattern}`;
            // it returns the setup for the dialog, including
            // used component, buttons, props, etc.
            'load' => function () {
              return [
                // what dialog component to use
                'component' => 'k-form-dialog',
                'props' => [
                  // field definition for the form dialog
                  'fields' => [ ... ],
                  // the prefilled model data
                  'value' => [ ... ]
                ]
              ];
            },
            // ...
          ]
        ]
      ];
    }
  ]
]);
```

### `submit` callback

The `submit` function is called once the dialog is submitted and defines the actions triggered by the event but also the response the Panel will receive.

```php
Kirby::plugin('yourname/todos', [
  'areas' => [
    'todos' => function ($kirby) {
      return [
        'dialogs' => [
          'todos/create' => [
            // ...

            // the submit event is creating a POST route at
            // `/panel/dialogs/{pattern}`;
            // the submit button of the dialog is automatically
            // wired to fire the POST request with the form
            // data or whatever data the dialog provides
            'submit' => function () {
              // create todo
              return true;
            }
          ]
        ]
      ];
    }
  ]
]);
```

The dialog's `submit` callback has multiple ways to interact with the component presented in the Panel via it's response:

`return void|null|false`
Returning nothing or `false` is interpreted as a 404. It suggests that the model could not be found.

`return true`
Returning true is interpreted as a success and will automatically close the dialog.

`return [ ... ]`
By returning an array, you gain more control of what happens when the dialog closes by passing data to the event:

```php
return [
  'event' => 'todo.create',
  'data'  => [
    // some data for the event
  ],
];
```

`throw new Exception`
Any exception is interpreted as an error and will show the error message box in the dialog containing the exception message

`Panel::go()`
You can redirect the Panel to a different location after submitting the dialog by calling:

```php
Panel::go('some/path');
```

<since v="5.1.0">
### Controller classes

Instead of defining the dialog directly as an array with `load` and `submit` keys, you can pass a controller class name or a closure that returns an object with `load` and `submit` methods. If the named class defines a static `::for()` method, Kirby will call it to create the instance.

```php
Kirby::plugin('yourname/todos', [
  'areas' => [
    'todos' => function () {
      return [
        'dialogs' => [
          'todos/create' => [
            'controller' => TodoCreateDialogController::class
          ],
          'todos/edit' => [
            'controller' => fn () => new TodoEditDialogController()
          ]
        ]
      ];
    }
  ]
]);
```
</since>

## Extending dialogs

We've seen above, how to create entirely new dialogs. But you can also replace or extend the Panel's default core dialogs:

```php
<?php

Kirby::plugin('custom/dialog', [
  'areas' => [
    'site' => function ($kirby) {
      return [
        'dialogs' => [
          'page.changeStatus' => [
            'load' => function (string $id) {
              // custom dialog setup
            },
            'submit' => function (string $id) {
              // custom dialog submitter action
            }
          ]
        ]
      ];
    },
  ]
]);
```

You have multiple options to extend a core dialog: You can keep the `submit` handler and only replace the `load` setup, you can change both or you can load an entirely new custom dialog component and modify the entire look of the dialog. It's all possible.

Check out the dialog docs above to learn more about dialog setups. It also helps to look at our original source code for dialogs. You can find the dialog code in <a href="https://github.com/getkirby/kirby/blob/main/config/areas">`/kirby/config/areas`</a>. Check out dialog files in the `site`, `users` and `files` subfolders.

### Reusing core functionalities

When you plan to extend a dialog, you might want to fall back to Kirby's core behaviour in some cases. This can be done by loading the core code:

```php
<?php

Kirby::plugin('custom/dialog', [
  'areas' => [
    'site' => function ($kirby) {
      return [
        'dialogs' => [
          'page.changeStatus' => [
            'load' => function (string $id) use ($kirby) {
              $page = Find::page($id);

              if ($page->id() === 'blog') {
                // return some custom dialog setup for the blog
              }

              return $kirby->core()->area('site')['dialogs']['page.changeStatus']['load']($id);
            }
          ]
        ]
      ];
    },
  ]
]);
```

## Core dialogs

Area | Dialog name
- | -
`languages` | `language.create`
`languages` | `language.delete`
`languages` | `language.update`
`site` | `page.changeSort`
`site` | `page.changeStatus`
`site` | `page.changeTemplate`
`site` | `page.changeTitle`
`site` | `page.create`
`site` | `page.delete`
`site` | `page.duplicate`
`site` | `page.file.changeName`
`site` | `page.file.changeSort`
`site` | `page.file.delete`
`site` | `site.changeTitle`
`site` | `site.file.changeName`
`site` | `site.file.changeSort`
`site` | `site.file.delete`
`users` | `user.create`
`users` | `user.changeEmail`
`users` | `user.changeLanguage`
`users` | `user.changeName`
`users` | `user.changePassword`
`users` | `user.changeRole`
`users` | `user.delete`
`users` | `user.file.changeName`
`users` | `user.file.changeSort`
`users` | `user.file.delete`