Please Disable Your Browser Adblock Extension for our site and Refresh This Page!

our ads are user friendly, we do not serve popup ads. We serve responsible ads!

Refresh Page
Skip to main content
On . By CodimTh
Category:

How to add custom mode form to entities in Drupal 8 & 9

in this article we will discover how to use 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).

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

 

form display

 

And the User entity now has a new Profil 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.

 

custom display settings

 

After we activate Profil mode then we can 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, Picture and Job fields that have been created for the User entity.

 

form display

 

To finalize this we will use a custom module that we will call mymodule.

Let's create mymodule.info.yml file:

type: module
name: My Module
description: My Module description
package: Custom
core_version_requirement: ^8.8.0 || ^9.0

 

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 mymodule.module:

<?php


/**
 * Implements hook_entity_type_build().
 */
function mymodule_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 ProfilCustomForm by extending the Class AccountForm.

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

mymodule.user.profil:
  path: '/user/{user}/profil'
  defaults:
    _entity_form: 'user.profil'
    _title: 'Profil'
  requirements:
    _entity_access: 'user.update'
    user: \d+
  options:
    _admin_route: FALSE

 

Now we will create a dynamic menu entry in the user account menu, in order to give an access link to users. In the file mymodule.links.menu.yml, let's add an entry to create the corresponding menu link.

mymodule.user.profil:
  title: 'Profil'
  weight: 1
  route_name: mymodule.user.profil
  base_route: entity.user.canonical
  menu_name: account
  class: Drupal\mymodule\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.

 

<?php

namespace Drupal\mymodule\Plugin\Menu;

use Drupal\Core\Menu\MenuLinkDefault;
use Drupal\Core\Url;
use Drupal\user\UserInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Menu\StaticMenuLinkOverridesInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;

/**
 * Profile Menu Link
 */
class ProfilUserBase extends MenuLinkDefault implements ContainerFactoryPluginInterface {

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManager
   */
  protected $entityTypeManager;

  /**
   * The current route match service.
   *
   * @var \Drupal\Core\Routing\CurrentRouteMatch
   */
  protected $currentRouteMatch;

  /**
   * The current user.
   *
   * @var \Drupal\Core\Session\AccountInterface
   */
  protected $currentUser;

  /**
   * Constructs a new MenuLinkDefault.
   *
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param \Drupal\Core\Menu\StaticMenuLinkOverridesInterface $static_override
   *   The static override storage.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager service.
   * @param \Drupal\Core\Routing\RouteMatchInterface $current_route_match
   *   The current route match service.
   * @param \Drupal\Core\Session\AccountInterface $current_user
   *   The current user.
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, StaticMenuLinkOverridesInterface $static_override, EntityTypeManagerInterface $entity_type_manager, RouteMatchInterface $current_route_match, AccountInterface $current_user) {
    parent::__construct($configuration, $plugin_id, $plugin_definition, $static_override);
    $this->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();
  }

}

 

Finally here is an example of our profil form:

form display

 

 

 

Comments

Add new comment

Restricted HTML

Search

Page Facebook

Become a patron

If you need some help or you search a Drupal freelancer don't hesitate to contact us.

 

Contact Us

All the content is FREE but I still need your help

 

Become a patreon