Search by

fivejars / media_directories_element

oleksandr.riumshyn

Provides the media_directories form element: the Media Directories browser widget for custom forms.

Package info

github.com/fivejars/media_directories_element

Type:drupal-module

pkg:composer/fivejars/media_directories_element

Statistics

Installs: 10

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.0.0 2026-11-02 09:07 UTC

This package is auto-updated.

Last update: 2026-11-02 09:09:43 UTC


README

Provides the media_directories form element: the Media Directories browser widget for custom forms that have no field to attach a widget to (Layout Builder section settings, block and plugin configuration forms, settings forms).

The element renders the same markup as the media_directories_browser_widget field widget, so it looks and behaves the same: an "Add media" button opening the browser modal, sortable preview tiles with Edit / Remove, and a cardinality hint.

It is a drop-in replacement for the media_library element of Media Library Form API Element: it accepts the same #default_value formats and returns the same submitted value, so switching only needs a new #type.

Requirements

  • Drupal 11
  • Media Directories, with its media_directories_browser submodule

Installation

Media Directories has no stable release yet, and Composer ignores stability flags of dependencies, so a site with minimum-stability: stable requires it explicitly first:

composer require drupal/media_directories:^3.0@RC
composer require fivejars/media_directories_element
drush en media_directories_element

Usage

$form['image'] = [
  '#type' => 'media_directories',
  '#title' => $this->t('Image'),
  '#default_value' => $media_id,
  '#cardinality' => 1,
  '#allowed_bundles' => ['image'],
];

On submit (including programmatic submissions with any #default_value format), the value is a comma-separated string of media IDs ('42', '1,2,3'), or '' when nothing is selected:

$ids = array_filter(explode(',', $form_state->getValue('image')));

Properties

Property Default Description
#default_value NULL Pre-selected media: NULL, an ID (42), a comma-separated string ('1,2,3') or an array of IDs ([1, 2, 3]).
#cardinality 1 Maximum number of items, a positive integer; -1 for unlimited. Anything else falls back to 1.
#allowed_bundles [] Allowed media type machine names; empty for all.
#button_label 'Add media' Label of the button opening the browser.
#collapsible FALSE Render a <details> instead of a <fieldset>.
#collapsed FALSE Start a collapsible element collapsed.
#open_when_empty FALSE Keep a collapsed element open while no media is selected.

#title, #description, #required and #states work as on any form element.

Validation

The value is checked server side, so a tampered or stale value can't pick media the user may not:

  • Deleted media drops out.
  • Newly picked media of a bundle not in #allowed_bundles, or that the current user may not view, drops out.
  • Media already saved in #default_value that the user may not pick (e.g. unpublished, or of a bundle no longer allowed) is kept, shown as an "Unavailable media" tile the user can remove. Re-saving a form never drops it silently.
  • More than #cardinality items is a validation error.

Off-canvas forms

The widget opens a tile's "Edit" form in the off-canvas dialog. When the element is itself rendered in off-canvas (e.g. Layout Builder), that would replace the form being edited, so there the Edit form opens in a modal dialog instead, and saving it closes only the modal.

Tests

vendor/bin/phpunit -c web/core web/modules/contrib/media_directories_element/tests

MediaDirectoriesTest covers the element itself. ParentContractTest checks what the element reuses from media_directories_browser (widget JS selectors, library, preview template variables, quick edit route, media service): run it after updating Media Directories, and a failure names what changed.

Migrating from media_library_form_element

Replace '#type' => 'media_library' with '#type' => 'media_directories'. #allowed_bundles, #cardinality and #default_value keep their meaning, and the submitted value has the same format.