Form http://lobsterr.me/ en How to render programatically custom entity form mode in Drupal? http://lobsterr.me/post/how-render-programatically-custom-entity-form-mode-drupal <span class="field field--name-title field--type-string field--label-hidden">How to render programatically custom entity form mode in Drupal?</span> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/user/1" typeof="schema:Person" property="schema:name" datatype="">LOBsTerr</span></span> <span class="field field--name-created field--type-created field--label-hidden">09/12/2019</span> <div class="field field--name-f-content field--type-entity-reference-revisions field--label-hidden field__items"> <div class="field__item"> <div class="paragraph paragraph--type--l-text paragraph--view-mode--default"> <div class="clearfix text-formatted field field--name-f-text field--type-text-long field--label-hidden field__item"><p>Sometime we want to render entity form on a custom page or even a block. It is possible to do in Drupal 8, because we can create custom entity form mode.</p> <p>Let's imagine we have a node type "<em>Post</em>" and  this content type has a lot of custom fields. We have technical field "<em>E-mails</em>" and we want to send e-mails, when someone comments this node.</p> <p>For the sake of the example we don't want to "pollute" the main node form with "<em>E-mails</em>" field and we want to create a separate form mode "email_settings" for it.</p> <p>If you try to display it programatically, you will face the exception:</p> <pre> <code class="language-php">public function emailSettings($node) { return $this-&gt;entityFormBuilder()-&gt;getForm($node, 'email_settings'); }</code></pre> <p> </p> <pre> <code class="language-php">The website encountered an unexpected error. Please try again later. Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException: The "node" entity type did not specify a "email_settings" form class. in Drupal\Core\Entity\EntityTypeManager-&gt;getFormObject() (line 223 of core/lib/Drupal/Core/Entity/EntityTypeManager.php). Drupal\Core\Entity\EntityFormBuilder-&gt;getForm(Object, 'email_settings') (Line: 10) Drupal\custom_entity_form_mode\Controller\CustomEntityFormModeController-&gt;emailSettings(Object) call_user_func_array(Array, Array) (Line: 123) Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber-&gt;Drupal\Core\EventSubscriber\{closure}() (Line: 582) Drupal\Core\Render\Renderer-&gt;executeInRenderContext(Object, Object) (Line: 124) Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber-&gt;wrapControllerExecutionInRenderContext(Array, Array) (Line: 97) Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber-&gt;Drupal\Core\EventSubscriber\{closure}() (Line: 151) Symfony\Component\HttpKernel\HttpKernel-&gt;handleRaw(Object, 1) (Line: 68) Symfony\Component\HttpKernel\HttpKernel-&gt;handle(Object, 1, 1) (Line: 57) Drupal\Core\StackMiddleware\Session-&gt;handle(Object, 1, 1) (Line: 47) Drupal\Core\StackMiddleware\KernelPreHandle-&gt;handle(Object, 1, 1) (Line: 106) Drupal\page_cache\StackMiddleware\PageCache-&gt;pass(Object, 1, 1) (Line: 85) Drupal\page_cache\StackMiddleware\PageCache-&gt;handle(Object, 1, 1) (Line: 47) Drupal\Core\StackMiddleware\ReverseProxyMiddleware-&gt;handle(Object, 1, 1) (Line: 52) Drupal\Core\StackMiddleware\NegotiationMiddleware-&gt;handle(Object, 1, 1) (Line: 23) Stack\StackedHttpKernel-&gt;handle(Object, 1, 1) (Line: 693) Drupal\Core\DrupalKernel-&gt;handle(Object) (Line: 19)</code></pre> <p>but it the same time if we use "default" form mode, it works perfectly</p> <pre> <code class="language-php">public function emailSettings($node) { return $this-&gt;entityFormBuilder()-&gt;getForm($node, 'default'); }</code></pre> <p>Why it happens? Well, it is quite simple the entity, in our case node, just has no idea how to handle our custom form mode. To be more precise entity doesn't know, which class to use to handle form mode.</p> <p>If you check node entity annotation, there is no information about our custom form mode. Unfortunately, It is not done automatically.<br />  </p> <pre> <code class="language-yaml"> * "form" = { * "default" = "Drupal\node\NodeForm", * "delete" = "Drupal\node\Form\NodeDeleteForm", * "edit" = "Drupal\node\NodeForm", * "delete-multiple-confirm" = "Drupal\node\Form\DeleteMultiple" * },</code></pre> <p>We have to alter the entity for this we will use hook_entity_type_alter. Full code could be found here: <a href="https://github.com/LOBsTerr/drupal-modules-examples/tree/master/custom_entity_form_mode">https://github.com/LOBsTerr/drupal-modules-examples/tree/master/custom_entity_form_mode</a></p> <pre> <code class="language-php">/** * Implements hook_entity_type_alter(). */ function custom_entity_form_mode_entity_type_alter(array &amp;$entity_types) { // You can provide more complex logic and checks here, we are sure that node // module is active and it is enabled in our case. $default_handler_class = $entity_types['node']-&gt;getHandlerClasses()['form']['default']; $entity_types['node']-&gt;setFormClass('emails_settings', $default_handler_class); }</code></pre> <p>Now you can create a node of content type, for which you have create form mode and open your custom page. In our example /email-settings/[nid]</p> <p> </p> <p>Now you can display your form in any place you want</p> <p> </p> </div> </div> </div> </div> <div class="field field--name-f-tags field--type-entity-reference field--label-hidden field__items"> <div class="field__item btn btn-secondary"><a href="/tags/entity" hreflang="en">Entity</a></div> <div class="field__item btn btn-secondary"><a href="/tags/form" hreflang="en">Form</a></div> <div class="field__item btn btn-secondary"><a href="/tags/drupal-9" hreflang="en">Drupal 9</a></div> <div class="field__item btn btn-secondary"><a href="/tags/entity-api" hreflang="en">Entity API</a></div> </div> <section class="field field--name-f-comments field--type-comment field--label-above comment-wrapper"> </section> Thu, 12 Sep 2019 08:53:37 +0000 LOBsTerr 13 at http://lobsterr.me