Upgrade Your Drupal Skills

We trained 1,000+ Drupal Developers over the last decade.

See Advanced Courses NAH, I know Enough

Provide a custom mode form to entities with Drupal 8

Like display modes that allow you to display an entity in multiple ways, Drupal 8 allows you to create multiple form modes that can be used on entities, whether they are users, taxonomy terms, contents or any custom entity. Let's discover here how to use these form modes, from their creation to their use to customize the input of a user's information, for example.

The creation of form modes is quite simple and can be done in a few clicks, from the administration interface (from the path /admin/structure/display-modes/form).

Drupal 8 form modes

Let's add a new form mode that we will call for example Profil.

Form mode Profil

And the User entity now has a new Profile form mode, in addition to the existing Register form mode (used for the registration form on a Drupal 8 site).

And we find our new form mode on the configuration page of the forms display (path /admin/config/people/accounts/form-display) of Drupal users.
 

Profil form

That we can activate so that we can then configure which fields will be rendered in this form mode. For example, we can configure this form mode to fill only the First name, Last name, Organization and Picture fields that have been created for the User entity.

Form profil configuration

So far so good. But how do we use our new form mode? From which path?

To finalize this we will use a small module that we will call my_module.

This module will allow us to declare our new form mode for the User entity, and to create a route, as well as a menu, which will allow us to access and complete our form.

First, let's declare this form mode and associate a Class with it, from the file my_module.module.

/**
 * Implements hook_entity_type_build().
 */
function my_module_entity_type_build(array &$entity_types) {
  $entity_types['user']->setFormClass('profil', 'Drupal\user\ProfileForm');
}

Here we associate the default form class User ProfileForm with our profil form mode. We could just as easily have used a Class MyProfilCustomForm by extending the Class AccountForm.

All we have to do now is create a route, from the file my_module.routing.yml, and we can then access our form.

my_module.user.profile:
  path: '/user/{user}/profil'
  defaults:
    _entity_form: 'user.profil'
    _title: 'Profil'
  requirements:
    _entity_access: 'user.update'
    _custom_access: '\Drupal\my_module\Access\MyModuleUserAccess::editProfil'
    user: \d+
  options:
    _admin_route: FALSE

From the route declaration, we specify the path (/user/{user}/profile), the form mode to be used for the User entity, specify route access rights (the right to modify a user, as well as customized permissions if necessary), and can also specify whether the route corresponds to an administration route, or not, to define the theme under which the form will be rendered (backoffice or frontoffice).

To finalize our new form mode, we will create a dynamic menu entry in the user account menu, in order to give an access link to users or administrators. In the file my_module.links.menu.yml, let's add an entry to create the corresponding menu link.

my_module.user.profil:
  title: 'Profil'
  weight: 10
  route_name: my_module.user.profil
  base_route: entity.user.canonical
  menu_name: user-account
  class: Drupal\my_module\Plugin\Menu\ProfilUserBase

What is notable here, in this menu entry, is the class property that will allow us to define the dynamic {user} parameter of the route corresponding to this menu entry. 

This ProfileUserBase Class will only return the ID of the accessed user, if the menu link is displayed on the user's page, or return the ID of the connected user if it is not, otherwise.

entityTypeManager = $entity_type_manager;
    $this->currentRouteMatch = $current_route_match;
    $this->currentUser = $current_user;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('menu_link.static.overrides'),
      $container->get('entity_type.manager'),
      $container->get('current_route_match'),
      $container->get('current_user')
    );
  }

  public function getRouteParameters() {
    return ['user' => $this->getUserIdFromRoute()];
  }

  /**
   * {@inheritdoc}
   */
  public function getCacheContexts() {
    return ['user', 'url'];
  }


  /**
   * Get the Account user id from the request or fallback to current user.
   *
   * @return int
   */
  public function getUserIdFromRoute() {
    $user = $this->currentRouteMatch->getParameter('user');
    if ($user instanceof AccountInterface) {
     return $user->id();
    }
    elseif (!empty($user)) {
      $user = $this->entityTypeManager->getStorage('user')->load($user);
      if($user instanceof AccountInterface) {
        return $user->id();
      }
    }

    return $this->currentUser->id();
  }

}

And now you can use your new form mode that you can customize at will, either from the graphical interface or from a customized Form Class allowing you to introduce any business and/or complex logic easily.

Finally, I can't conclude this post on the Drupal 8 form mode without mentioning the Form Mode Manager module which can allow you to do all this without the need for a Drupal developer. Depending on your needs and the level of expertise you want, you can choose one or the other of these solutions. But this may be the subject of another blog post.

Author: 
Original Post: 

About Drupal Sun

Drupal Sun is an Evolving Web project. It allows you to:

  • Do full-text search on all the articles in Drupal Planet (thanks to Apache Solr)
  • Facet based on tags, author, or feed
  • Flip through articles quickly (with j/k or arrow keys) to find what you're interested in
  • View the entire article text inline, or in the context of the site where it was created

See the blog post at Evolving Web

Evolving Web