Components
Programatically rendering entity form in Drupal 8, 9 and 10 is easy, provided that you want to render it using the default form mode.
// Load existing node
$node = \Drupal\node\Entity\Node::load(1);
// or create a new node
$node = \Drupal::entityTypeManager()->getStorage('node')->create(['type' => 'article']);
$form = \Drupal::service('entity.form_builder')->getForm($node);
If you want to render it using any other form mode like this for example:
$node = \Drupal\node\Entity\Node::load(1);
$form = \Drupal::service('entity.form_builder')->getForm($node, 'compact');
you will have to alter the entity definition and add your own form handler. Otherwise, you'll get the following error:
Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException: The "node" entity type did not specify a "compact" form class.
To add your own form class you can use the hook_entity_type_alter hook like this:
/**
* Implements hook_entity_type_alter().
*
* Alters the entity definition and adds our own form handlers.
*/
function MY_MODULE_entity_type_alter(array &$entity_types) {
$form_modes = \Drupal::service('entity_display.repository')
->getAllFormModes();
foreach ($form_modes as $entity_type => $display_modes) {
if ($entity_type !== 'node') {
continue;
}
$type = $entity_types[$entity_type];
foreach ($display_modes as $machine_name => $form_display) {
if (isset($type->getHandlerClasses()['form']['default'])) {
$default_handler_class = $type->getHandlerClasses()['form']['default'];
$type->setFormClass($machine_name, $default_handler_class);
}
}
}
}
In summary, while rendering an entity form programmatically in Drupal 8, 9 and 10 is straightforward with the default form mode, using custom form modes requires altering the entity definition and specifying appropriate form handlers to avoid errors.