Design ====== The design of the backend is ready for any kind of application. It's been created with `Bootstrap 5`_, `Font Awesome icons`_ and some custom CSS and JavaScript code; all managed by `Webpack`_ via Symfony's `Webpack Encore`_. Like any other Symfony bundle, assets are copied to (or symlinked from) the ``public/bundles/`` directory of your application when installing or updating the bundle. If this doesn't work for any reason, your backend won't display the proper CSS/JS styles. In those cases, run this command to install those assets manually: .. code-block:: terminal # remove the --symlink option if your system doesn't support symbolic links $ php bin/console assets:install --symlink Depending on your needs, there are several ways of customizing the design. Some of them require pure CSS/JavaScript code and others require overriding and/or creating new Twig templates. .. _template-customization: Modifying Backend Templates --------------------------- Backend pages are created with multiple Twig templates and fragments. You can modify them in two ways: * **Override EasyAdmin templates** using Symfony's mechanism to override templates (this is the same for all bundles, not only EasyAdmin); * **Replace EasyAdmin templates** using EasyAdmin features. Overriding Templates ~~~~~~~~~~~~~~~~~~~~ .. tip:: Instead of using Symfony mechanism to override templates, you may consider using a similar but more powerful feature provided by EasyAdmin to replace templates, as explained in :ref:`the next section `. Following Symfony's mechanism to `override templates from bundles`_, you must create the ``templates/bundles/EasyAdminBundle/`` directory in your application and then create new templates with the same path as the original templates. For example:: your-project/ ├─ ... └─ templates/ └─ bundles/ └─ EasyAdminBundle/ ├─ layout.html.twig ├─ menu.html.twig ├─ crud/ │ ├─ index.html.twig │ ├─ detail.html.twig │ └─ field/ │ ├─ country.html.twig │ └─ text.html.twig ├─ label/ │ └─ null.html.twig └─ page/ ├─ content.html.twig └─ login.html.twig Instead of creating the new templates from scratch, you can extend from the original templates and change only the parts you want to override. However, you must use a special syntax inside ``extends`` to avoid an infinite loop: .. code-block:: twig {# templates/bundles/EasyAdminBundle/layout.html.twig #} {# DON'T DO THIS: it will cause an infinite loop #} {% extends '@EasyAdmin/layout.html.twig' %} {# DO THIS: the '!' symbol tells Symfony to extend from the original template #} {% extends '@!EasyAdmin/layout.html.twig' %} {% block sidebar %} {# ... #} {% endblock %} .. _replacing_templates: Replacing Templates ~~~~~~~~~~~~~~~~~~~ This option allows you to render certain parts of the backend with your own Twig templates. First, you can replace some templates globally in the :doc:`dashboard `:: use EasyCorp\Bundle\EasyAdminBundle\Config\Crud; use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractDashboardController; class DashboardController extends AbstractDashboardController { // ... public function configureCrud(): Crud { return Crud::new() // ... // the first argument is the "template name", which is the same as the // Twig path but without the `@EasyAdmin/` prefix ->overrideTemplate('label/null', 'admin/labels/my_null_label.html.twig') ->overrideTemplates([ 'crud/index' => 'admin/pages/index.html.twig', 'crud/field/textarea' => 'admin/fields/dynamic_textarea.html.twig', ]) ; } } You can also replace templates per :doc:`CRUD controller ` (this overrides any change done in the dashboard):: namespace App\Controller\Admin; use EasyCorp\Bundle\EasyAdminBundle\Config\Crud; use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController; class ProductCrudController extends AbstractCrudController { // ... public function configureCrud(Crud $crud): Crud { return $crud // ... ->overrideTemplate('crud/layout', 'admin/advanced_layout.html.twig') ->overrideTemplates([ 'crud/field/text' => 'admin/product/field_id.html.twig', 'label/null' => 'admin/labels/null_product.html.twig', ]) ; } } Fields And Actions Templates ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Each :doc:`field ` (and each :doc:`action `) defines a ``setTemplatePath()`` method to set the Twig template used to render that specific field (or action):: TextField::new('...', '...') // ... ->setTemplatePath('custom_fields/text.html.twig'); // ... Action::new('...', '...') // ... ->setTemplatePath('admin/actions/my_custom_action.html.twig'); The ``setTemplatePath()`` method only applies to fields displayed on the ``index`` and ``detail`` pages. Read the next section to learn how to customize fields in the ``new`` and ``edit`` pages, which use Symfony forms. Form Field Templates ~~~~~~~~~~~~~~~~~~~~ EasyAdmin provides a ready-to-use `form theme`_ based on Bootstrap 5. Dashboards and CRUD controllers define ``addFormTheme(string $themePath)`` and ``setFormThemes(array $themePaths)`` methods so you can `customize individual form fields`_ using your own form theme. Imagine a form field where you want to include a ```` element that links to additional information. If the field is called ``title`` and belongs to a ``Product`` entity, the configuration would look like this:: TextField::new('title') // ... ->setFormTypeOptions([ 'block_name' => 'custom_title', ]); The next step is to define the template fragment used by that field, which requires to know the `form fragment naming rules`_ defined by Symfony: .. code-block:: twig {# templates/admin/form.html.twig #} {# note that the Twig block name starts with an uppercase letter ('_Product_...' instead of '_product_...') because the first part of the block name is the unmodified entity name #} {% block _Product_custom_title_widget %} {# ... #} More information {% endblock %} Finally, add this custom theme to the list of themes used to render backend forms:: namespace App\Controller\Admin; use EasyCorp\Bundle\EasyAdminBundle\Config\Crud; use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController; class ProductCrudController extends AbstractCrudController { // ... public function configureCrud(Crud $crud): Crud { return $crud // ... // don't forget to add EasyAdmin's form theme at the end of the list // (otherwise you'll lose all the styles for the rest of form fields) ->setFormThemes(['admin/form.html.twig', '@EasyAdmin/crud/form_theme.html.twig']) ; } } .. note:: You can also override the form widget by using the original field name. In the example above it would look like this: ``{% block _Product_title_widget %}``. The full syntax is: ``{% block ___widget %}``. .. _crud-design-custom-web-assets: Adding Custom Web Assets ------------------------ Use the ``configureAssets()`` method in the :doc:`dashboard ` and/or the :doc:`CRUD controllers ` to add your own CSS and JavaScript files:: namespace App\Controller\Admin; use EasyCorp\Bundle\EasyAdminBundle\Config\Assets; use EasyCorp\Bundle\EasyAdminBundle\Config\Crud; use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController; class ProductCrudController extends AbstractCrudController { // ... public function configureAssets(Assets $assets): Assets { return $assets // adds the CSS and JS assets associated to the given Webpack Encore entry // it's equivalent to adding these inside the element: // {{ encore_entry_link_tags('...') }} and {{ encore_entry_script_tags('...') }} ->addWebpackEncoreEntry('admin-app') // it's equivalent to adding this inside the element: // ->addCssFile('build/admin.css') ->addCssFile('https://example.org/css/admin2.css') // it's equivalent to adding this inside the element: // ->addJsFile('build/admin.js') ->addJsFile('https://example.org/js/admin2.js') // use these generic methods to add any code before or // the contents are included "as is" in the rendered page (without escaping them) ->addHtmlContentToHead('') ->addHtmlContentToBody('') ->addHtmlContentToBody('') ; } } If you need to customize the HTML attributes or other features of the ```` and ``