Customizing Entity Form Displaysfor Drupal 11 , 10 , 9 , and 8

Last updated :  

Not every field belongs on every form. A "created" timestamp might make sense on a display page but not on an add form; an internal notes field might belong on the edit form but never the quick-add version. Drupal handles this with form displays — configuration, not code, that controls which fields appear, in what order, and with which widget, per form mode.

What you'll learn in this lesson

  • What a form display actually is, and how it's different from a view display
  • How the "default" form mode relates to custom form modes
  • Where form-display configuration actually lives on disk
  • Why this is almost always the right tool before you reach for a code-level override

Form displays are per entity type + bundle + mode

Every content entity type gets a "default" form display automatically. If your entity type supports bundles (content types, in node's case), each bundle can have its own. On top of "default," you can define additional named form modes — a "quick_add" mode with only three fields, for example — and each mode gets its own independent field layout.

What the configuration actually looks like

langcode: en
status: true
dependencies:
  module:
    - content_entity_example
id: content_entity_example_contact.content_entity_example_contact.default
targetEntityType: content_entity_example_contact
bundle: content_entity_example_contact
mode: default
content:
  name:
    type: string_textfield
    weight: 0
    region: content
  first_name:
    type: string_textfield
    weight: 1
    region: content
hidden:
  created: true
  changed: true

Two sections matter here: content lists every field that's visible, with its widget type and display order (weight); hidden lists fields that exist on the entity but are deliberately excluded from this particular form. Reordering fields, swapping a widget, or hiding a field is entirely a matter of editing this config — no PHP, no touching ContactForm.php at all.

This is genuinely the first tool to reach for: a surprising amount of "I need to customize my entity form" turns out to be solvable purely through form-display config — reordering fields, hiding one, changing a widget. Reaching for a buildForm() override (as in earlier lessons) should be reserved for logic config can't express, like the language-selector or uniqueness-validation examples from this section.

See it for yourself

If your site has Field UI enabled, visit /admin/structure/content-entity-example-contact-type/form-display (or the equivalent "Manage form display" tab for your entity type) and try dragging a field to reorder it — that action writes directly to the YAML shape shown above.

Quick check: you want the "Language" field this section's earlier lessons added via buildForm() to also be reorderable through the form-display UI, like every other field. What would that take? (It would need to become a real field on the entity — defined in baseFieldDefinitions() — rather than a form element hand-added in PHP, since only genuine entity fields participate in form-display configuration.)

Key takeaways

  • Form displays are per entity type, per bundle, per form mode — "default" always exists automatically.
  • The content/hidden split in a form display's YAML controls exactly which fields appear and in what order, without any PHP.
  • Reordering fields and swapping widgets should go through form-display config first; reach for a buildForm() override only for logic config genuinely can't express.
  • Only real entity fields (declared in baseFieldDefinitions()) participate in form-display configuration — form elements added manually in PHP don't.

Coming up next

You've now seen the config-driven side of entity forms. Next, we return to the code-driven side one more time: hook_entity_form_alter(), for changes that need to reach across every entity form on the site, not just one form class.