Contents

Introduction

CRUD View is an Admin Generator for CakePHP built on top of the CRUD plugin. It is flexible enough that it can be used only for certain parts of your applications and aims to be flexible enough so it requires little configuration.

The core philosophy behind CRUD and CRUD view is that you only need to deal with aspects of your applications. This means that you should be able to listen for events in order to modify how it looks and how it behaves.

Another goal of CRUD View is that its parts should be replaceable where possible, but it should offer a sane, ready-to-use Admin interface by default only by providing the database it needs to work with.

When to use CRUD View

  • When you need to implement an Admin interface that is generated from the Backend. If you want to create your interface using only javascript, please only use the CRUD plugin as it will help you creating the required API.

  • When you want to take care about the rules of your data processing and not too much how the interface is going to look like.

  • If you prefer tweaking, overriding and configuring instead of doing everything from scratch.

Status

This plugin is still in early development status, things may change suddenly, but it can be used in real projects already.

Installation

Installing CRUD view requires only a few steps

Requirements

  • CakePHP 4.x

Getting the Code

The recommended installation method for this plugin is by using composer.

In your aplication forlder execute:

composer require friendsofcake/crud-view

It is highly recommended that you install the Search plugin as well:

composer require friendsofcake/search

Loading the plugin

Execute the following lines from your application folder:

bin/cake plugin load Crud
bin/cake plugin load CrudView
bin/cake plugin load BootstrapUI
bin/cake plugin load Search

Quick Start

You are busy, and you just want to get things done™, so let’s get going.

After installation, you are ready to CRUD-ify your app.

App Controller

First, configure the Crud plugin.

Configuring the AppController

If you haven’t configured the CRUD plugin already, add the following lines to your src/Controller/AppController.php file

<?php
declare(strict_types=1);

namespace App\Controller;

class AppController extends \Cake\Controller\Controller
{
    use \Crud\Controller\ControllerTrait;

    public function initialize(): void
    {
        parent::initialize();

        $this->loadComponent('RequestHandler');
        $this->loadComponent('Flash');

        $this->loadComponent('Crud.Crud', [
            'actions' => [
                'Crud.Index',
                'Crud.View',
                'Crud.Add',
                'Crud.Edit',
                'Crud.Delete',
                'Crud.Lookup',
            ],
            'listeners' => [
                // New listeners that need to be added:
                'CrudView.View',
                'Crud.Redirect',
                'Crud.RelatedModels',
                // If you need searching. Generally it's better to load these
                // only in the controller for which you need searching.
                'Crud.Search',
                'CrudView.ViewSearch',
            ]
        ]);
    }

    /**
     * Before render callback.
     *
     * @param \Cake\Event\Event $event The beforeRender event.
     * @return void
     */
    public function beforeRender(\Cake\Event\EventInterface $event)
    {
        if ($this->viewBuilder()->getClassName() === null) {
            $this->viewBuilder()->setClassName('CrudView\View\CrudView');
        }
    }
}

If you are familair with the CRUD plugin already, you will immediately understand that Crud view is simply a listener for the events generated by the plugin. If this is new to you, don’t worry, it will be explained in the following sections.

Using It In Your Controllers

Any controller inheriting from AppController will automatically implement the specified actions loaded int the CRUD component configuration. Therefore, you can just leave your controller code empty!

<?php
namespace App\Controller;

class CategoriesController extends AppController
{
    // No code here, but we have all actions available to use!
}

View the Results

You can now access your categories list by pointing your browser to http://example.com/categories. Browse around your new Admin interface for each of the controllers you have in your application.

Basic Usage

Getting comfortable with CRUD View usually depends on getting grips of the CRUD plugin first. Since much of the features this plugin provides are implemented on top of the features exposed by the CRUD plugin, much of the documentation will just repeat what it is possible in it.

Implementing an Index List

Rendering a list of the rows in a table is a matter of just adding the Crud.Index action to the Crud component and the CrudView.View as a listener.

public function initialize(): void
{
    $this->loadComponent('Crud.Crud', [
        'actions' => [
            'Crud.Index',
            // ...
        ],
        'listeners' => [
            'CrudView.View',
            // ...
        ]
    ]);
}

There is no need to have an `index() function in your controller. But you can implement it to customize both the behavior and looks of the index listing page.

<?php
declare(strict_types=1);

namespace App\Controller;

class ArticlesController extends AppController
{
    public function index()
    {
        // Your customization and configuration changes here
        return $this->Crud->execute();
    }
}

Most configuration changes need to be done by using the config() function in the action object. The config() method can be used for both reading and writing.

public function index()
{
    $action = $this->Crud->action(); // Gets the IndexAction object
    debug($action->getConfig()); // Show all configuration related to this action
    return $this->Crud->execute();
}

Below is a list of the configuration values that can be used and how they affect the rendering of your view:

Providing Associations to be Displayed

By default all belongsTo and hasOne associations are fetched in the pagination query for the index view. If you wanted to blacklist one of those associations.

Fore example you may want to not fetch the Authors association of the Articles as you don’t plan to show it in the index table:

public function index()
{
    $action = $this->Crud->action();
    $action->setConfig('scaffold.relations_blacklist', ['Authors', ...]);
    return $this->Crud->execute();
}

If you want to be specific about which association need to be fetched, just use the scaffold.relations configuration key:

public function index()
{
    $action = $this->Crud->action();
    $action->setConfig('scaffold.relations', ['Categories', 'Tags']);
    return $this->Crud->execute();
}

Alternatively, you can use the Crud plugin’s beforePaginate method to alter the contain() list for the pagination query:

public function index()
{
    $this->Crud->on('beforePaginate', function ($event) {
        $paginationQuery  = $event->getSubject()->query;
        $paginationQuery->contain([
            'Categories',
            'Authors' => ['fields' => ['id', 'name']]
        ]);
    });
    return $this->Crud->execute();
}

Specifying the Fields to be Displayed

If you wish to control which fields should be displayed in the index table, use the scaffold.fields and scaffold.fields_blacklist configuration keys. By default, all fields from the table will be displayed

For example, let’s avoid the created and modified fields from being displayed in the index table:

public function index()
{
    $action = $this->Crud->action();
    $action->setConfig('scaffold.fields_blacklist', ['created', 'modified']);
    return $this->Crud->execute();
}

You can also be specific about the fields, and the order, in which they should appear in the index table:

public function index()
{
    $action = $this->Crud->action();
    $action->setConfig('scaffold.fields', ['title', 'body', 'category', 'published_time']);
    return $this->Crud->execute();
}

Linking to Actions

At the end of each row in the index table, there will be a list of actions links, such as View, Edit and Delete. If you wish to control which actions should be displayed or not, use the scaffold.actions and scaffold.actions_blacklist configurations keys.

For example, imagine we wanted to remove the Delete link from the index table:

public function index()
{
    $action = $this->Crud->action();
    $action->setConfig('scaffold.actions_blacklist', ['delete']);
    return $this->Crud->execute();
}

Likewise, you can instruct the CrudView plugin on which actions should be specifically displayed in the index view:

public function index()
{
    $action = $this->Crud->action();
    $action->setConfig('scaffold.actions', ['view', 'add', 'edit']);
    return $this->Crud->execute();
}

Implementing an Add Action

If you have read this far, you know almost everything there is to know about configuring any type of action using CrudView, but being explicit about what is available in all of them will not hurt.

Implementing the Add action is done by adding the Crud.View action to the Crud component configuration:

public function initialize()
{
    $this->loadComponent('Crud.Crud', [
        'actions' => [
            'Crud.Add',
            // ...
        ],
        'listeners' => [
            'CrudView.View',
            'Crud.Redirect'
            'Crud.RelatedModels'
            // ...
        ]
    ]);
}

For the Add action it is recommended that you add the Crud.Redirect and Crud.RelatedModels listeners. The former will help adding more redirection options after saving the record and the latter will send the required information to the view so that the select widgets for associations get the correct options.

Implementing an Edit Action

Likewise, edit actions can be implemented by adding the right configuration to the Crud component. This is the recommended configuration:

public function initialize(): void
{
    $this->loadComponent('Crud.Crud', [
        'actions' => [
            'Crud.Edit',
            // ...
        ],
        'listeners' => [
            'CrudView.View',
            'Crud.Redirect'
            'Crud.RelatedModels'
            // ...
        ]
    ]);
}

As with the Add action, the Crud.Redirect and Crud.RelatedModels listeners will help handling redirection after save and help populate the select widgets for associations.

Specifying the Fields to be Displayed

When adding or editing a record, you probably want to avoid some of the fields from being displayed as an input in the form. Use the scaffold.fields and scaffold.fields_blacklist.

For example, let’s avoid having inputs for the created and modified fields in the form:

public function add()
{
    $action = $this->Crud->action();
    $action->setConfig('scaffold.fields_blacklist', ['created', 'modified']);
    return $this->Crud->execute();
}

It is also possible to directly specify which fields should have an input in the form by using the scaffold.fields configuration key:

public function edit()
{
    $action = $this->Crud->action();
    $action->setConfig('scaffold.fields', ['title', 'body', 'category_id']);
    return $this->Crud->execute();
}

You can pass attributes or change the form input type to specific fields when using the scaffold.fields configuration key. For example, you may want to add the placeholder property to the title input:

public function add()
{
    $action = $this->Crud->action();
    $action->setConfig('scaffold.fields', [
        'title' => ['placeholder' => 'Insert a title here'],
        'body',
        'category_id'
    ]);
    return $this->Crud->execute();
}

The configuration can be used in both add and edit actions.

Limiting the Associations Information

By default the RelatedModels listener will populate the select boxes in the form by looking up all the records from the associated tables. For example, when creating an Article, if you have a Categories association it will populate the select box for the category_id field.

For a full explanation on RelatedModels please visit the CRUD Documentation for the RelatedModelsListener.

If you want to alter the query that is used for an association in particular, you can use the relatedModels event:

public function add()
{
    $this->Crud->on('relatedModel', function(\Cake\Event\Event $event) {
        if ($event->getSubject()->association->name() === 'Categories') {
            $event->getSubject()->query->limit(3);
            $event->getSubject()->query->where(['is_active' => true]);
        }
    });
    return $this->Crud->execute();
}

The callback can be used in both add and edit actions.

Pre-Selecting Association Options

In order to pre-select the right association options in an edit action, for example pre-selecting the category_id in the categories select box, CrudView will automatically fetch all associations for the entity to be modified.

This can be wasteful at times, especially if you only allow a few associations to be saved. For this case, you may use the scaffold.relations and scaffold.relations_blacklist to control what associations are added to contain():

public function edit()
{
    $action $this->Crud->action();
    // Only fetch association info for Categories and Tags
    $action->setConfig('scaffold.relations', ['Categories', 'Tags']);
    return $this->Crud->execute();
}

If you choose to use scaffold.relations_blacklist, then you need only specify those association that should not be added to contain():

public function edit()
{
    $action $this->Crud->action();
    // Only fetch association info for Categories and Tags
    $action->setConfig('scaffold.relations_blacklist', ['Authors']);
    return $this->Crud->execute();
}

Disabling the Extra Submit Buttons

You may have noticed already that in the add form there are multiple submit buttons. If you wish to only keep the “Save” button, you set the scaffold.form_submit_extra_buttons configuration key to false:

public function add()
{
    $action = $this->Crud->action();
    $action->setConfig('scaffold.form_submit_extra_buttons', false);
    return $this->Crud->execute();
}

Implementing a View Action

Implementing a View action, for displaying the full information for a record, including its associations is also achieved via configuring the Crud component:

public function initialize()
{
    $this->loadComponent('Crud.Crud', [
        'actions' => [
            'Crud.View',
            // ...
        ],
        'listeners' => [
            'CrudView.View',
            // ...
        ]
    ]);
}

For this type of action there are no extra recommended listeners that you can apply, but there are some configuration options you can use to customize the information that is displayed.

Specifying the Fields to be Displayed

If you wish to control which fields should be displayed in the view table, use the scaffold.fields and scaffold.fields_blacklist configuration keys. By default, all fields from the table will be displayed

For example, let’s avoid the created and modified fields from being displayed in the view table:

public function view()
{
    $action = $this->Crud->action();
    $action->setConfig('scaffold.fields_blacklist', ['created', 'modified']);
    return $this->Crud->execute();
}

You can also be specific about the fields, and the order, in which they should appear in the index table:

public function view()
{
    $action = $this->Crud->action();
    $action->setConfig('scaffold.fields', ['title', 'body', 'category', 'published_time']);
    return $this->Crud->execute();
}

Providing Associations to be Displayed

By default all associations are fetched so they can be displayed in the view action. Similarly to the Index action, you can use the scaffold.relations and the scaffold.relations_blacklist

Fore example you may want to not fetch the Authors association of the Articles as it may be implicit by the currently logged-in user:

public function view()
{
    $action = $this->Crud->action();
    $action->setConfig('scaffold.relations_blacklist', ['Authors', ...]);
    return $this->Crud->execute();
}

If you want to be specific about which association need to be fetched, just use the scaffold.relations configuration key:

public function view()
{
    $action = $this->Crud->action();
    $action->setConfig('scaffold.relations', ['Categories', 'Tags']);
    return $this->Crud->execute();
}

Alternatively, you can use the Crud plugin’s beforePaginate method to alter the contain() list for the pagination query:

public function view()
{
    $this->Crud->on('beforeFind', function ($event) {
        $event->getSubject()->query->contain([
            'Categories',
            'Authors' => ['fields' => ['id', 'name']]
        ]);
    });
    return $this->Crud->execute();
}

Bulk Actions

The Crud plugin provides bulk actions which can be easily used with crud view.

To set up crud action in controller do something like this in initialize method.

$this->loadComponent('Crud.Crud', [
    'actions' => [
        'deleteAll' => [
            'className' => 'Crud.Bulk/Delete',
        ],
    ]
]);

Once a bulk action has been mapped, the scaffold.bulk_actions configuration key can be specified. The scaffold.bulk_actions configuration key takes an array of key/value pairs, where the key is the url and the value is the title.

$action = $this->Crud->action();
$action->setConfig('scaffold.bulk_actions', [
    Router::url(['action' => 'deleteAll']) => __('Delete records'),
]);

Going Forward

The following chapters will show you how to customize the output of each field, how to override parts of the templates and implementing search auto-completion.

Customizing Templates

Despite CrudView being quite smart at guessing how to display your data and having great defaults, it is very often that you need to customize the look and feel of your Admin application.

Customizing Fields

Fields may be specified via the scaffold.fields configuration key. By default, this will contain a list of all columns associated with the Table being in scope. To limit the fields used, simply specify an array of fields.

$action = $this->Crud->action();
$action->setConfig('scaffold.fields', ['title', 'description']);

You may also specify an options array. For forms, CrudView makes use of the FormHelper::inputs() method and will pass your array values as options when generating the output.

$action = $this->Crud->action();
$action->setConfig('scaffold.fields', [
    'title',
    'thread_id' => [
        'type' => 'text'
    ],
    'featured' => [
        'checked' => 'checked'
    ]
]);

Setting options for specific fields

If you wish to use the default automatic field population functionality but want to specify settings for a few of the fields, you can use the scaffold.field_settings configuration key:

$action = $this->Crud->action();
$action->setConfig('scaffold.field_settings', [
    'title' => [
        // options here
    ]
]);

Removing Fields from output

You may also use the scaffold.fields_blacklist configuration key to remove fields from the output if you are using the default automatic field population functionality:

$action = $this->Crud->action();
$action->setConfig('scaffold.fields_blacklist', ['created', 'modified']);

Formatting with a Callable

Note

This functionality currently only applies to index and view pages.

The most immediate way of formatting a field is by passing a callable function or object to the formatter option. Callable functions or objects will receive 5 arguments:

  • $name The name of the field to be displayed

  • $value The value of the field that should be outputted

  • $entity The entity object from which the field was extracted

  • $options An array of options passed to the CrudView helper when the field is being processed

  • $View The view object in use during formatting

For example, imagine that when displaying the published_time property, we wanted to also display who approved the article:

$action = $this->Crud->action();
$action->setConfig('scaffold.fields', [
    'title',
    'published_time' => [
        'formatter' => function ($name, $value, $entity) {
            return $value->nice() . sprintf(' (Approved by %s)', $entity->approver->name);
        }
    ],
]);

You may also specify formatters using the scaffold.field_settings configuration key. This is useful if you want to display all fields but wish to only configure the settings for one or two.

$action = $this->Crud->action();
$action->setConfig('scaffold.field_settings', [
    'published_time' => [
        'formatter' => function ($name, Time $value, Entity $entity) {
            return $value->nice() . sprintf(' (Approved by %s)', $entity->approver->name);
        }
    ],
]);

In some cases, it may be useful to access a helper within the callable. For instance, you might want to create a link:

$action = $this->Crud->action();
$action->setConfig('scaffold.fields', [
    'title',
    'external_id' => [
        'formatter' => function ($name, $value, $entity, $options, $View) {
            return $View->Html->link($name, sprintf('https://example.com/view/%d', $value));
        }
    ],
]);

You can also keep your code DRY by configuring the CrudViewHelper to use a callable formatter based on column type. For .e.g.

// In controller action or preferably in beforeRender()
$this->viewBuilder()->setHelpers([
    'CrudView' => [
        'className' => 'CrudView.CrudView',
        'fieldFormatters' => [
            // Key can be any valid column type of table schema.
            'datetime' => function ($name, $value, $entity, $options, $View) {
                return $View->Time->nice($value);
            },
            'boolean' => function ($name, $value, $entity, $options, $View) {
                return $value ? 'Yes' : 'No';
            },
        ],
    ],
]);

Formatting with an Element

Note

This functionality currently only applies to index and view pages.

Sometimes you want to execute more complex formatting logic, that may involve the use of view helpers or outputting HTML. Since building HTML outside of the view layer is not ideal, you can use the element formatter for any of your fields.

For example, consider this example where we want to link the published_time to the same index action by passing some search arguments:

$action = $this->Crud->action();
$action->setConfig('scaffold.fields', [
    'published_time' => [
        'formatter' => 'element',
        'element' => 'search/published_time',
        'action' => 'index'
    ]
]);

We have instructed the formatter to use search/published_time element. Then, it is just a matter of creating the element file with the right content:

// templates/element/search/published_time.ctp

echo $this->Html->link($value->timeAgoInWords(), [
    'action' => $options['action'],
    'published_time' => $value->format('Y-m-d')
]);

After this, when displaying the published_time field, there will the will be a link similar to this one:

<a href="/articles?published_time=2015-06-23">4 days ago</a>

Element files will have available at least the following variables:

  • $value: The value of the field

  • $field: The name of the field it is intended to be rendered

  • $context: The entity from which the value came from

  • $options: The array of options associated to the field as passed in scaffold.fields

Changing Field Header or Label Names

CrudView infers the name of the field by splitting the field so that it can be read by a human. Sometimes this is just not enough, or you may wish to show an entirely different header in a table or label in a form.

Changing Form Input Labels

In our add() and edit() actions, you can specify the input label for title for any of the fields by using the scaffold.fields configuration

$action = $this->Crud->action();
$action->setConfig('scaffold.fields', [
    'author_id' => ['label' => 'Author Name'],
    // The rest of the fields to display here
]);

Adding Controller Actions to utilize Crud Actions

It’s easy to add an action to a controller that makes use of another CrudView action.

This does use the template provided by the edit action:

public function account() {
    $this->Crud->mapAction('account', [
        'className' => 'Crud.Edit',
        'view' => 'edit',
    ]);
    return $this->Crud->execute(null, $this->Auth->user('id'));
}

By default, it can be overwritten by providing a custom register.ctp:

public function register() {
    $this->Crud->mapAction('register', [
        'className' => 'Crud.Add',
    ]);
    return $this->Crud->execute();
}

Overriding Template Elements

All the CrudView templates are built from several elements that can be overridden by creating them in your own templates/element folder. The following sections will list all the elements that can be overridden for each type of action.

In general, if you want to override a template, it is a good idea to copy the original implementation from vendor/friendsofcake/crud-view/templates/element

Site Title Options

Every page has what’s called the site title on the left side of the menu bar. If you want, you can customize it.

Site Title

You can use the scaffold.site_title config variable to modify the title. If not set, it will fallback to the following alternative:

  • Configure::read('CrudView.siteTitle')

$action = $this->Crud->action();
$action->setConfig('scaffold.site_title', 'My Admin Site');

Site Title Image

You can use the scaffold.site_title_image config variable to modify the title link. If set, it replaces scaffold.site_title.

$action = $this->Crud->action();
// Use an image included in your codebase
$action->setConfig('scaffold.site_title_image', 'site_image.png');

// Use an exact url
$action->setConfig('scaffold.site_title_image', 'http://www.google.com/images/logos/google_logo_41.png');

Page Sidebar Navigation

The “sidebar navigation” shown on the left normally shows the a link to the Crud index action for all tables. You can customize it using the scaffold.sidebar_navigation configuration key.

Specifying which tables to show

You can specify the exact tables to show in the sidebar via the scaffold.tables configuration key:

// only show the posts table
$this->Crud->action()->setConfig('scaffold.tables', ['posts']);

Blacklisting tables

As an alternative to whitelisting tables via scaffold.tables, you can use the scaffold.tables_blacklist configuration key to specify tables to exclude from the output:

// do not show the ``phinxlog`` and ``users`` tables
$this->Crud->action()->setConfig('scaffold.tables_blacklist', [
    'phinxlog',
    'users',
]);

You can also specify a global tables blacklist by setting CrudView.tablesBlacklist configuration key. By default the phinxlog table is blacklisted.

Configure::write('CrudView.tablesBlacklist', ['phinxlog']);

Disabling the Sidebar Navigation

The sidebar navigation can also be completely disabled by setting the value to false.

$this->Crud->action()->setConfig('scaffold.sidebar_navigation', false);

Custom Menus

The sidebar navigation is just like any other menu in the system. You can provide your own menu to be rendered in its place:

use CrudView\Menu\MenuDivider;
use CrudView\Menu\MenuItem;

$this->Crud->action()->setConfig('scaffold.sidebar_navigation', [
    new MenuItem('Section Header'),
    new MenuItem(
        'CrudView Docs',
        'https://crud-view.readthedocs.io/en/latest/contents.html',
        ['target' => 'blank']
    ),
    new MenuItem(
        'Profile',
        ['controller' => 'Users', 'action' => 'profile']
    ),
    new MenuItem(
        'Inbox',
        ['controller' => 'Users', 'action' => 'inbox']
    ),
    new MenuItem(
        'Settings',
        ['controller' => 'Site', 'action' => 'settings']
    ),
    new MenuDivider(),
    new MenuItem(
        'Log Out',
        ['controller' => 'Users', 'action' => 'logout']
    )
]);

Utility Navigation

The “utility navigation” shown at the top right normally shows the current user and a link to log out. It can be controlled via the scaffold.utility_navigation configuration key

Disabling the Utility Navigation

The utility navigation can also be completely disabled by setting the value to false.

$this->Crud->action()->setConfig('scaffold.utility_navigation', false);

Custom Menus

The utility navigation is just like any other menu in the system. You can provide your own menu to be rendered in its place:

use CrudView\Menu\MenuDivider;
use CrudView\Menu\MenuDropdown;
use CrudView\Menu\MenuItem;

$action = $this->Crud->action();
$action->setConfig('scaffold.utility_navigation', [
    new MenuItem(
        'CrudView Docs',
        'https://crud-view.readthedocs.io/en/latest/contents.html',
        ['target' => 'blank']
    ),
    new MenuDropdown(
        'John Smith',
        [
            new MenuItem(
                'Profile',
                ['controller' => 'Users', 'action' => 'profile']
            ),
            new MenuItem(
                'Inbox',
                ['controller' => 'Users', 'action' => 'inbox']
            ),
            new MenuItem(
                'Settings',
                ['controller' => 'Site', 'action' => 'settings']
            ),
            new MenuDivider(),
            new MenuItem(
                'Log Out',
                ['controller' => 'Users', 'action' => 'logout']
            )
        ]
    )
]);

Customizing the Dashboard Page

The “dashboard” can be used to display a default landing page for CrudView-powered admin sites. It is made of several \Cake\View\Cell instances, and can be extended to display items other than what is shipped with CrudView.

To use the “Dashboard”, the custom DashboardAction needs to be mapped:

public function initialize(): void
{
    parent::initialize();

    $this->Crud->mapAction('dashboard', 'CrudView.Dashboard');
}

Browsing to this mapped action will result in a blank page. To customize it, a \CrudView\Dashboard\Dashboard can be configured on the scaffold.dashboard key:

public function dashboard()
{
    $dashboard = new \CrudView\Dashboard\Dashboard();
    $this->Crud->action()->setConfig('scaffold.dashboard', $dashboard);
    return $this->Crud->execute();
}

The \CrudView\Dashboard\Dashboard instance takes two arguments:

  • title: The title for the dashboard view. Defaults to Dashboard.

  • columns A number of columns to display on the view. Defaults to 1.

public function dashboard()
{
    // setting both the title and the number of columns
    $dashboard = new \CrudView\Dashboard\Dashboard(__('Site Administration'), 12);
    $this->Crud->action()->setConfig('scaffold.dashboard', $dashboard);
    return $this->Crud->execute();
}

Adding Cells to the Dashboard

Any number of cells may be added to the Dashboard. All cells must extend the \Cake\View\Cell class.

Cells can be added via the Dashboard::addToColumn() method. It takes a cell instance and a column number as arguments.

// assuming the `CellTrait` is in use, we can generate a cell via `$this->cell()`
$someCell = $this->cell('SomeCell');
$dashboard = new \CrudView\Dashboard\Dashboard(__('Site Administration'), 2);

// add to the first column
$dashboard->addToColumn($someCell);

// configure the column to add to
$dashboard->addToColumn($someCell, 2);

CrudView ships with the DashboardTable cell by default.

CrudView.DashboardTable

This can be used to display links to items in your application or offiste.

public function dashboard()
{
    // setting both the title and the number of columns
    $dashboard = new \CrudView\Dashboard\Dashboard(__('Site Administration'), 1);
    $dashboard->addToColumn($this->cell('CrudView.DashboardTable', [
        'title' => 'Important Links'
    ]));

    $this->Crud->action()->setConfig('scaffold.dashboard', $dashboard);
    return $this->Crud->execute();
}

In the above example, only a title to the DashboardTable, which will show a single subheading for your Dashboard.

In addition to showing a title, it is also possible to show a list of links. This can be done by adding a links key with an array of LinkItem objects as the value. Links containing urls for external websites will open in a new window by default.

public function dashboard()
{
    // setting both the title and the number of columns
    $dashboard = new \CrudView\Dashboard\Dashboard(__('Site Administration'), 1);
    $dashboard->addToColumn($this->cell('CrudView.DashboardTable', [
        'title' => 'Important Links',
        'links' => [
            new LinkItem('Example', 'https://example.com', ['target' => '_blank']),
        ],
    ]));

    $this->Crud->action()->setConfig('scaffold.dashboard', $dashboard);
    return $this->Crud->execute();
}

There is also a special kind of LinkItem called an ActionLinkItem. This has a fourth argument is an array of LinkItem objects. It can be used to show embedded action links on the same row.

public function dashboard()
{
    $dashboard = new \CrudView\Dashboard\Dashboard(__('Site Administration'), 1);
    $dashboard->addToColumn($this->cell('CrudView.DashboardTable', [
        'title' => 'Important Links',
        'links' => [
            new ActionLinkItem('Posts', ['controller' => 'Posts'], [], [
                new LinkItem('Add', ['controller' => 'Posts', 'action' => 'add']),
            ]),
        ],
    ]));

    $this->Crud->action()->setConfig('scaffold.dashboard', $dashboard);
    return $this->Crud->execute();
}

Available Viewblocks

The following custom view blocks are available for use within forms:

  • dashboard.before: Rendered before the entire dashboard is rendered.

  • dashboard.after: Rendered after the entire dashboard is rendered.

Available Elements

All the CrudView templates are built from several elements that can be overridden by creating them in your own templates/element folder. The following sections will list all the elements that can be overridden for each type of action.

In general, if you want to override a template, it is a good idea to copy the original implementation from vendor/friendsofcake/crud-view/templates/element

action-header

Create templates/element/action-header.ctp to have full control over what is displayed at the top of the page. This is shared across all page types.

Customizing the Index Page

Customizing Fields

Fields may be specified via the scaffold.fields configuration key. By default, this will contain a list of all columns associated with the Table being in scope. To limit the fields used, simply specify an array of fields:

$action = $this->Crud->action();
$action->setConfig('scaffold.fields', ['title', 'description']);

Setting options for specific fields

If you wish to use the default automatic field population functionality but want to specify settings for a few of the fields, you can use the scaffold.field_settings configuration key:

$action = $this->Crud->action();
$action->setConfig('scaffold.field_settings', [
    'title' => [
        // options here
    ]
]);

Removing Fields from output

You may also use the scaffold.fields_blacklist configuration key to remove fields from the output if you are using the default automatic field population functionality:

$action = $this->Crud->action();
$action->setConfig('scaffold.fields_blacklist', ['created', 'modified']);

Formatting with a Callable

Note

This functionality currently only applies to index and view pages.

The most immediate way of formatting a field is by passing a callable function or object to the formatter option. Callable functions or objects will receive 5 arguments:

  • $name The name of the field to be displayed

  • $value The value of the field that should be outputted

  • $entity The entity object from which the field was extracted

  • $options An array of options passed to the CrudView helper when the field is being processed

  • $View The view object in use during formatting

For example, imagine that when displaying the published_time property, we wanted to also display who approved the article:

$action = $this->Crud->action();
$action->setConfig('scaffold.fields', [
    'title',
    'published_time' => [
        'formatter' => function ($name, $value, $entity) {
            return $value->nice() . sprintf(' (Approved by %s)', $entity->approver->name);
        }
    ],
]);

You may also specify formatters using the scaffold.field_settings configuration key. This is useful if you want to display all fields but wish to only configure the settings for one or two.

$action = $this->Crud->action();
$action->setConfig('scaffold.field_settings', [
    'published_time' => [
        'formatter' => function ($name, Time $value, Entity $entity) {
            return $value->nice() . sprintf(' (Approved by %s)', $entity->approver->name);
        }
    ],
]);

In some cases, it may be useful to access a helper within the callable. For instance, you might want to create a link:

$action = $this->Crud->action();
$action->setConfig('scaffold.fields', [
    'title',
    'external_id' => [
        'formatter' => function ($name, $value, $entity, $options, $View) {
            return $View->Html->link($name, sprintf('https://example.com/view/%d', $value));
        }
    ],
]);

You can also keep your code DRY by configuring the CrudViewHelper to use a callable formatter based on column type. For .e.g.

// In controller action or preferably in beforeRender()
$this->viewBuilder()->setHelpers([
    'CrudView' => [
        'className' => 'CrudView.CrudView',
        'fieldFormatters' => [
            // Key can be any valid column type of table schema.
            'datetime' => function ($name, $value, $entity, $options, $View) {
                return $View->Time->nice($value);
            },
            'boolean' => function ($name, $value, $entity, $options, $View) {
                return $value ? 'Yes' : 'No';
            },
        ],
    ],
]);

Formatting with an Element

Note

This functionality currently only applies to index and view pages.

Sometimes you want to execute more complex formatting logic, that may involve the use of view helpers or outputting HTML. Since building HTML outside of the view layer is not ideal, you can use the element formatter for any of your fields.

For example, consider this example where we want to link the published_time to the same index action by passing some search arguments:

$action = $this->Crud->action();
$action->setConfig('scaffold.fields', [
    'published_time' => [
        'formatter' => 'element',
        'element' => 'search/published_time',
        'action' => 'index'
    ]
]);

We have instructed the formatter to use search/published_time element. Then, it is just a matter of creating the element file with the right content:

// templates/element/search/published_time.ctp

echo $this->Html->link($value->timeAgoInWords(), [
    'action' => $options['action'],
    'published_time' => $value->format('Y-m-d')
]);

After this, when displaying the published_time field, there will the will be a link similar to this one:

<a href="/articles?published_time=2015-06-23">4 days ago</a>

Element files will have available at least the following variables:

  • $value: The value of the field

  • $field: The name of the field it is intended to be rendered

  • $context: The entity from which the value came from

  • $options: The array of options associated to the field as passed in scaffold.fields

Column sorting

By default sorting links are generated for index page table’s column headers using the PaginatorHelper. You can disable the link generation by using the disableSort option:

$action = $this->Crud->action();
$action->setConfig('scaffold.fields', [
    'title' => [
        'disableSort' => true,
    ]
]);

Index Buttons

By default, the included index buttons are generated based on the mapped Crud actions. You can customize available buttons by using the scaffold.actions key:

$action = $this->Crud->action();

// restrict to just the add button, which will show up globally
$action->setConfig('scaffold.actions', [
    'add'
]);

// restrict to just the delete/edit/view actions, which are scoped to entities
$action->setConfig('scaffold.actions', [
    'delete',
    'edit',
    'view',
]);

You can also specify configuration for actions, which will be used when generating action buttons.

$action = $this->Crud->action();
$action->setConfig('scaffold.actions', [
    'duplicate' => [
        // An alternative title for the action
        'link_title' => 'Duplicate this record',

        // A url that this action should point to
        'url' => ['action' => 'jk-actually-this-action'],

        // The HTTP method to use. Defaults to GET. All others result in
        // a ``FormHelper::postLink``
        'method' => 'POST',

        // Whether to scope the action to a single entity or the entire table
        // Options: ``entity``, ``table``
        'scope' => 'entity',

        // All other options are passed in as normal to the options array
        'other' => 'options',
    ]
]);

Customizing primaryKey position in the url

For entity-scoped actions, we will append the primaryKey of the record to the link by default:

$action = $this->Crud->action();

// For the PostsController, will generate
// /posts/translate/english/1
$action->setConfig('scaffold.actions', [
    'translate' => [
        'url' => ['action' => 'translate', 'english']
    ]
]);

We can specify the token :primaryKey:. Rather than appending the primaryKey, we will replace this token in the url as many times as specified.

$action = $this->Crud->action();

// For the PostsController, will generate
// /posts/translate/1/english
$action->setConfig('scaffold.actions', [
    'translate' => [
        'url' => ['action' => 'translate', ':primaryKey:', 'english']
    ]
]);

Blacklisting Index Buttons

If you wish to blacklist certain action buttons from showing up, you can use the scaffold.actions_blacklist configuration key. This can be useful when many Crud action classes are mapped but should not all be shown on the main UI.

$action = $this->Crud->action();
$action->setConfig('scaffold.actions_blacklist', ['add', 'delete']);

By default, we blacklist the action which is mapped to Crud.LookupAction. As this action is meant to be used solely for autocompletion, it cannot be removed from the scaffold.actions_blacklist list.

Action Groups

You can group actions together using Action Groups. This will generate a dropdown for the group, and can be controlled by the scaffold.action_groups configuration key.

$action = $this->Crud->action();
$action->setConfig('scaffold.actions', ['view', 'edit', 'delete']);
$action->setConfig('scaffold.action_groups', [
    'Actions' => [
        'view',
        'edit',
        'delete',
    ],
]);

All actions specified in an action group must be included in the scaffold.actions key.

You can specify multiple action groups:

$action = $this->Crud->action();
$action->setConfig('scaffold.actions', ['view', 'edit', 'delete', 'disable', 'delete']);
$action->setConfig('scaffold.action_groups', [
    'Actions' => [
        'view',
        'edit',
        'delete',
    ],
    'Destructive Actions' => [
        'disable',
        'delete',
    ]
]);

Finally, you can also set configuration for each entry in an action group:

$action = $this->Crud->action();
$action->setConfig('scaffold.actions', ['view', 'edit', 'delete', 'english', 'spanish']);
$action->setConfig('scaffold.action_groups', [
    'Actions' => [
        'view',
        'edit',
        'delete',
    ],
    'Translate' => [
        'english' => [
            'url' => ['action' => 'translate', 'english']
        ],
        'spanish' => [
            'url' => ['action' => 'translate', 'spanish']
        ],
    ]
]);

Bulk Actions

The Crud plugin provides bulk actions which can be easily used with crud view.

To set up crud action in controller do something like this in initialize method.

$this->loadComponent('Crud.Crud', [
    'actions' => [
        'deleteAll' => [
            'className' => 'Crud.Bulk/Delete',
        ],
    ]
]);

Once a bulk action has been mapped, the scaffold.bulk_actions configuration key can be specified. The scaffold.bulk_actions configuration key takes an array of key/value pairs, where the key is the url and the value is the title.

$action = $this->Crud->action();
$action->setConfig('scaffold.bulk_actions', [
    Router::url(['action' => 'deleteAll']) => __('Delete records'),
]);

Index Finder Scopes

In some cases, it is helpful to show quick links to pre-filtered datasets. Rather than force users to select all the filters, CrudView enables the ability to display “Finder Scope” links via the scaffold.index_finder_scopes configuration key. These are output below the action header, above the data that is being paginated.

The scaffold.index_finder_scopes option takes an array of finder scope data. Each sub-array should contain title and finder parameters.

$this->Crud->action()->setConfig('scaffold.index_finder_scopes', [
        [
            'title' => __('All'),
            'finder' => 'all',
        ],
        [
            'title' => __('Active'),
            'finder' => 'active',
        ],
        [
            'title' => __('Inactive'),
            'finder' => 'inactive',
        ],
]);

The all finder scope is special. This scope will be displayed by default, and should always be included in the scope list. It is not automatically injected.

Selecting a finder scope will reset any other querystring arguments. Selecting the all finder scope will result in being redirected to a page without querystring arguments.

Selecting a finder scope will not automatically apply the find to your paginated result-set. This must be done manually.

Example: Applying Finder Scopes

Note

This example assumes a simple blog application is being modified, with a posts database table containing the fields id, active, title, body, and created.

Once a finder scope is selected, it must still be applied to the paginated result-set. This can be done in the mapped action as follows:

public function index()
{
    $this->Crud->action()->setConfig('scaffold.index_finder_scopes', [
        [
            'title' => __('All'),
            'finder' => 'all',
        ],
        [
            'title' => __('Active'),
            'finder' => 'active',
        ],
        [
            'title' => __('Inactive'),
            'finder' => 'inactive',
        ],
    ]);

    // We don't need to check for `all` as it is the default findMethod
    if (in_array($this->request->getQuery('finder'), ['active', 'inactive'])) {
        $this->Crud->action()->config('findMethod', $this->request->getQuery('finder'));
    }
    return $this->Crud->execute();
}

Now that the findMethod can be mapped, the respective custom find methods must be created in the PostsTable class.

use Cake\ORM\Query;
use Cake\ORM\Table;

class PostsTable extends Table
{
    public function findActive(Query $query, array $options)
    {
        $query->where([$this->aliasField('active') => true]);

        return $query;
    }

    public function findInactive(Query $query, array $options)
    {
        $query->where([$this->aliasField('active') => false]);

        return $query;
    }
}

Index Filters

The ViewSearch listener generates filter inputs for filtering records on your index action. It requries friendsofcake/search <https://packagist.org/packages/friendsofcake/search> to be installed and filters configured for your model using the search manager.

<?php
declare(strict_types=1);

namespace App\Controller;
use App\Controller\AppController;

class SamplesController extends AppController
{
    public function initialize(): void
    {
        parent::initialize();
        // Enable PrgComponent so search form submissions
        // properly populate querystring parameters for the SearchListener
        $this->loadComponent('Search.Prg', [
            'actions' => [
                'index',
            ],
        ]);
    }

    public function index()
    {
        // Enable the SearchListener
        $this->Crud->addListener('search', 'Crud.Search', [
            // The search behavior collection to use. Default "default".
            'collection' => 'admin',
        ]);

        // Enable the ViewSearch listener
        $this->Crud->addListener('viewSearch', 'CrudView.ViewSearch', [
            // Indicates whether is listener is enabled.
            'enabled' => true,

            // Whether to use auto complete for select fields. Default `true`.
            // This requires you have `Crud.Lookup` action enabled for that
            // related model's controller.
            // http://crud.readthedocs.io/en/latest/actions/lookup.html
            'autocomplete' => true,

            // Whether to use selectize for select fields. Default `true`.
            'selectize' => true,

            // The search behavior collection to use. Default "default".
            'collection' => 'default',

            // Config for generating filter controls. If `null` the
            // filter controls will be derived based on filter collection.
            // You can use "form" key in filter config to specify control options.
            // Default `null`.
            'fields' => [
                // Key should be the filter name.
                'filter_1' => [
                    // Any option which you can use Form::control() options.
                ],
                // Control options for other filters.
            ]
        ]);

        return $this->Crud->execute();
    }
}

Here’s an e.g. of how configure filter controls options through search manager itself:

<?php
declare(strict_types=1);

namespace App\Model\Table;
use Cake\ORM\Table;

class SamplesTable extends Table
{
    public function initialize(array $config): void
    {
        parent::initialize($config);

        $this->addBehavior('Search.Search');
        $this->searchManager()
            ->useCollection('default')
            ->add('q', 'Search.Like', [
                'field' => ['title', 'body'],
                'form' => [
                    'data-foo' => 'bar'
                ]
            ])
            ->add('category_id', 'Search.Value', [
                'form' => [
                    'type' => 'select',
                    'class' => 'no-selectize'
                ]
            ]);
    }
}

Multiple Index Pages

Sometime you may want more than one index page for a resource to represent different views to the user. If multiple index pages exist, CrudView will automatically build links at the top of the index page. Including multiple views is simple and requires setting the index view in your action.

$action = $this->Crud->action();
$action->view('index');

Available Viewblocks

The following custom view blocks are available for use within forms:

  • form.sidebar: Rendered on the side of a form. Will also change the form width.

  • form.before_create: Rendered before FormHelper::create() is called.

  • form.after_create: Rendered after FormHelper::create() is called.

  • form.before_end: Rendered before FormHelper::end() is called.

  • form.after_end: Rendered after FormHelper::end() is called. Used by embedded Form::postLink() calls.

Available Elements

All the CrudView templates are built from several elements that can be overridden by creating them in your own templates/element folder. The following sections will list all the elements that can be overridden for each type of action.

In general, if you want to override a template, it is a good idea to copy the original implementation from vendor/friendsofcake/crud-view/templates/element

action-header

Create templates/element/action-header.ctp to have full control over what is displayed at the top of the page. This is shared across all page types.

form/buttons

Create templates/element/form/buttons.ctp to change what is displayed for form submission. You can expect the $formSubmitButtonText and $formSubmitExtraButtons variables to be available

Custom Index

To use a custom index element, you can set the scaffold.index_type config option.

$action = $this->Crud->action();
$action->setConfig('scaffold.index_type', 'an_element');

Available Variables

The following variables are available for use within the element:

  • fields: List of fields to show and their options

  • actions: A list of actions that can be displayed for the index page.

  • bulkActions: A list of bulk actions associated with this resource

  • primaryKey: The name of the record’s primary key field.

  • singularVar: The singular version of the resource name.

  • viewVar: Reference to the name of the variable holding all records.

  • plural of viewVar: The set of records.

Index as a Blog

Render your index page as a set of posts.

$action = $this->Crud->action();
$action->config('scaffold.index_type', 'blog');

Customizing the Blog fields

The blog index type has two main options:

  • scaffold.index_title_field: (default: displayField for current table) Controls the field used for the blog title.

  • scaffold.index_body_field: (default: body) Controls the field used for the blog body.

$action = $this->Crud->action();
$action->setConfig('scaffold.index_title_field', 'name');
$action->setConfig('scaffold.index_body_field', 'content');

Available Variables

The following variables are available for use within the element:

  • indexTitleField: The field containing the post title

  • indexBodyField: The field containing the post body

  • fields: List of fields to show and their options

  • actions: A list of actions that can be displayed for the index page.

  • bulkActions: A list of bulk actions associated with this resource

  • primaryKey: The name of the record’s primary key field.

  • singularVar: The singular version of the resource name.

  • viewVar: Reference to the name of the variable holding all records.

  • plural of viewVar: The set of records.

Index as a Table

By default, the index page is a table with each of the models content columns and links to show, edit and delete the object. There are many ways to customize what gets displayed.

Defining Columns

By default, all fields are displayed on the index page. To display an attribute or a method on a record, you can use the scaffold.fields config option.

$action = $this->Crud->action();
$action->setConfig('scaffold.fields', ['id', 'title']);

To specify the title used in the pagination header, you need to set scaffold.fields to an associative array and use the title parameter:

$action = $this->Crud->action();
$action->setConfig('scaffold.fields', [
  'author_id' => ['title' => 'Author Name'],
]);

Index Action Elements

All the CrudView templates are built from several elements that can be overridden by creating them in your own templates/element folder. The following sections will list all the elements that can be overridden for each type of action.

In general, if you want to override a template, it is a good idea to copy the original implementation from vendor/friendsofcake/crud-view/templates/element

search

Create templates/element/search.ctp for having full control over how the search filters are displayed in your pagination table. You can expect the $searchInputs and $searchOptions variables to be available

index/table

Create templates/element/index/table.ctp To implement your own table.

index/pagination

Create templates/element/index/pagination.ctp To implement your own pagination links and counter.

index/bulk_actions/table

Create templates/element/index/bulk_actions/table.ctp for changing how the bulk action inputs for the whole table. You can expect the $bulkActions, $primaryKey and $singularVar variables to be available.

index/bulk_actions/record

Create templates/element/index/bulk_actions/record.ctp for changing how the bulk action inputs for each row are displayed. You can expect the $bulkActions, $primaryKey and $singularVar variables to be available.

index/bulk_actions/form_start

Create templates/element/index/bulk_actions/form_start.ctp To customize the Form create call for bulk actions

index/bulk_actions/form_end

Create templates/element/index/bulk_actions/form_end.ctp To customize the Form end call for bulk actions

Customizing the Form Page

Customizing Fields

Fields may be specified via the scaffold.fields configuration key. By default, this will contain a list of all columns associated with the Table being in scope. To limit the fields used, simply specify an array of fields.

$action = $this->Crud->action();
$action->setConfig('scaffold.fields', ['title', 'description']);

You may also specify an options array. For forms, CrudView makes use of the FormHelper::inputs() method and will pass your array values as options when generating the output.

$action = $this->Crud->action();
$action->setConfig('scaffold.fields', [
    'title',
    'thread_id' => [
        'type' => 'text'
    ],
    'featured' => [
        'checked' => 'checked'
    ]
]);

Setting options for specific fields

If you wish to use the default automatic field population functionality but want to specify settings for a few of the fields, you can use the scaffold.field_settings configuration key:

$action = $this->Crud->action();
$action->setConfig('scaffold.field_settings', [
    'title' => [
        // options here
    ]
]);

Removing Fields from output

You may also use the scaffold.fields_blacklist configuration key to remove fields from the output if you are using the default automatic field population functionality:

$action = $this->Crud->action();
$action->setConfig('scaffold.fields_blacklist', ['created', 'modified']);

Grouping fields in tabs

You can group the form fields in tabs using the scaffold.form_tab_groups configuration key:

$action = $this->Crud->action();
$action->setConfig('scaffold.form_tab_groups', [
    'First Tab Header' => ['field_1', 'field_2'],
    'Second Tab Header' => ['field_3', 'field_4'],
]);

If there are fields which are not listed under any group they will be automatically shown under 1st tab with header Primary. You can customize the primary group’s name using scaffold.form_primary_tab config.

$action = $this->Crud->action();
$action->setConfig('scaffold.form_primary_tab', 'Key Info');

Form Submission

Form Submission Redirect

By default, the Crud plugin will redirect all form submissions to the controller’s index action. This can be changed by setting the _redirect_url view variable:

$this->set('_redirect_url', ['action' => 'home']);

Form Submission Check

By default, closing the a form page in your browser will result in lost data. However, you may force a user prompt by enabling dirty form checks using the scaffold.form_enable_dirty_check configuration key:

$action = $this->Crud->action();
$action->setConfig('scaffold.form_enable_dirty_check', true);

Submit Buttons

Changing the Submit Button Text

You can change the submit button text from it’s default using the scaffold.form_submit_button_text configuration key.

$action = $this->Crud->action();
$action->setConfig('scaffold.form_submit_button_text', _('Submit'));

Modifying the Default Extra Buttons

By default, we should the following extra buttons for forms:

  • Save & continue editing: Results in a form submission

  • Save & create new: Results in a form submission

  • Back: A link to the index page

To use the defaults, you may either omit the configuration key or set it to true:

$action = $this->Crud->action();
$action->setConfig('scaffold.form_submit_extra_buttons', true);

You can also customize this by using the scaffold.form_submit_extra_buttons configuration key as follows:

$action = $this->Crud->action();
$action->setConfig('scaffold.form_submit_extra_buttons', [
    [
        'title' => __d('crud', 'Save & continue editing'),
        'options' => ['class' => 'btn btn-success btn-save-continue', 'name' => '_edit', 'value' => true],
        'type' => 'button',
    ],
    [
        'title' => __d('crud', 'Save & create new'),
        'options' => ['class' => 'btn btn-success', 'name' => '_add', 'value' => true],
        'type' => 'button',
    ],
    [
        'title' => __d('crud', 'Back'),
        'url' => ['action' => 'index'],
        'options' => ['class' => 'btn btn-default', 'role' => 'button', 'value' => true],
        'type' => 'link',
    ],
]);

Specified values will override the defaults, and will be output in the order specified.

Modifying the Default Extra Left Buttons

By default, extra buttons appear on the right-hand side of forms. The left-hand side is managed separately, and will show the following by default

  • Delete: An embedded postLink for deleting the current entity. This only appears on the pages that are rendered via EditAction.

To use the defaults, you may either omit the configuration key or set it to true:

$action = $this->Crud->action();
$action->setConfig('scaffold.form_submit_extra_left_buttons', true);

You can also customize this by using the scaffold.form_submit_extra_left_buttons configuration key as follows:

$action = $this->Crud->action();
$action->setConfig('scaffold.form_submit_extra_left_buttons', [
    [
        'title' => __d('crud', 'Save & continue editing'),
        'options' => ['class' => 'btn btn-success btn-save-continue', 'name' => '_edit', 'value' => true],
        'type' => 'button',
    ],
]);

Disabling the Default Extra Buttons

Rather than modifying the default extra buttons, you can also disable them completely:

$action = $this->Crud->action();
$action->setConfig('scaffold.form_submit_extra_buttons', false);

Disabling the Default Extra Left Buttons

Disabling the default left extra buttons can also be done in a similar fashion:

$action = $this->Crud->action();
$action->setConfig('scaffold.form_submit_extra_left_buttons', false);

Available Viewblocks

The following custom view blocks are available for use within forms:

  • form.sidebar: Rendered on the side of a form. Will also change the form width.

  • form.before_create: Rendered before FormHelper::create() is called.

  • form.after_create: Rendered after FormHelper::create() is called.

  • form.before_end: Rendered before FormHelper::end() is called.

  • form.after_end: Rendered after FormHelper::end() is called. Used by embedded Form::postLink() calls.

Available Elements

All the CrudView templates are built from several elements that can be overridden by creating them in your own templates/element folder. The following sections will list all the elements that can be overridden for each type of action.

In general, if you want to override a template, it is a good idea to copy the original implementation from vendor/friendsofcake/crud-view/templates/element

action-header

Create templates/element/action-header.ctp to have full control over what is displayed at the top of the page. This is shared across all page types.

form/buttons

Create templates/element/form/buttons.ctp to change what is displayed for form submission. You can expect the $formSubmitButtonText and $formSubmitExtraButtons variables to be available

  v: latest
Versions
latest
stable
docs
Downloads
pdf
html
epub
On Read the Docs
Project Home
Builds
Downloads
On GitHub
View
Edit

Free document hosting provided by Read the Docs.