ICT:Drupal opener explained: Difference between revisions
Created page with "== Custom Media Library Opener for Heritage Digital Assets == In '''Drupal 11.3.5''', a custom "Opener" service allows the Media Library to be used as a standalone modal. This implementation restricts selection to '''one and only one''' asset and returns a rendered thumbnail to the parent page, mimicking the "classical" Media Library behavior without the full Field API overhead. === 1. Define the Service === Register the opener in your module's <code>your_module.servic..." |
No edit summary |
||
| Line 104: | Line 104: | ||
* <code>id="asset-preview-container"</code>: Where the thumbnail will appear. | * <code>id="asset-preview-container"</code>: Where the thumbnail will appear. | ||
* <code>id="selected-asset-id"</code>: A hidden input to store the ID for the backend. | * <code>id="selected-asset-id"</code>: A hidden input to store the ID for the backend. | ||
== Configuration: Custom View Mode == | |||
To ensure the selected heritage asset matches the project's design, we use a dedicated view mode instead of the generic library thumbnail. | |||
=== 1. UI Configuration Steps === | |||
# Go to '''Structure > Display modes > View modes''' and add a new "Media" mode named {{code|Heritage Asset Preview}}. | |||
# Navigate to '''Structure > Media types > [Your Type] > Manage display'''. | |||
# Enable the {{code|Heritage Asset Preview}} under '''Custom display settings'''. | |||
# Configure the layout: | |||
#* Hide all fields except the main file/image. | |||
#* Set the Format to '''Thumbnail''' and select a custom '''Image Style''' (e.g., {{code|heritage_large_preview}}). | |||
=== 2. Code Implementation === | |||
Update the {{code|getSelectionResponse}} method in {{code|HeritageAssetOpener.php}} to call this specific mode: | |||
<source lang="php"> | |||
// Render the media using our project-specific view mode | |||
$render_array = $view_builder->view($media, 'heritage_asset_preview'); | |||
</source> | |||
=== 3. CSS Styling === | |||
You can now target this specific preview in your theme: | |||
<source lang="css"> | |||
.heritage-thumbnail-wrapper [data-drupal-view-mode="heritage_asset_preview"] { | |||
border: 2px solid #a39161; /* Heritage gold border */ | |||
box-shadow: 3px 3px 10px rgba(0,0,0,0.2); | |||
max-width: 300px; | |||
} | |||
</source> | |||
[[Category:Drupal Development]] | [[Category:Drupal Development]] | ||
[[Category:Heritage Project Documentation]] | [[Category:Heritage Project Documentation]] | ||
Revision as of 09:53, 12 March 2026
Custom Media Library Opener for Heritage Digital Assets
In Drupal 11.3.5, a custom "Opener" service allows the Media Library to be used as a standalone modal. This implementation restricts selection to one and only one asset and returns a rendered thumbnail to the parent page, mimicking the "classical" Media Library behavior without the full Field API overhead.
1. Define the Service
Register the opener in your module's your_module.services.yml. You must tag it with media_library.opener so the system can identify it.
services:
your_module.heritage_opener:
class: Drupal\your_module\HeritageAssetOpener
arguments: ['@entity_type.manager']
tags:
- { name: media_library.opener }
2. The Opener Logic
Create src/HeritageAssetOpener.php. This class handles the permission check and generates the AJAX response to inject the thumbnail.
namespace Drupal\your_module;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\HtmlCommand;
use Drupal\Core\Ajax\InvokeCommand;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\media\Entity\Media;
use Drupal\media_library\MediaLibraryOpenerInterface;
use Drupal\media_library\MediaLibraryState;
class HeritageAssetOpener implements MediaLibraryOpenerInterface {
protected $entityTypeManager;
public function __construct(EntityTypeManagerInterface $entity_type_manager) {
$this->entityTypeManager = $entity_type_manager;
}
/**
* Checks if the user can access the media library in this context.
*/
public function checkAccess(MediaLibraryState $state, AccountInterface $account) {
return AccessResult::allowedIfHasPermission($account, 'view media');
}
/**
* Logic executed after clicking "Insert" in the modal.
*/
public function getSelectionResponse(MediaLibraryState $state, array $selected_ids) {
$selected_id = reset($selected_ids); // Force single selection logic
$media = Media::load($selected_id);
$response = new AjaxResponse();
if ($media) {
// Build the thumbnail using the 'media_library' view mode
$view_builder = $this->entityTypeManager->getViewBuilder('media');
$render_array = $view_builder->view($media, 'media_library');
// Inject the thumbnail into the UI
$response->addCommand(new HtmlCommand('#asset-preview-container', $render_array));
// Update a hidden field with the ID for form submission
$response->addCommand(new InvokeCommand('#selected-asset-id', 'val', [$selected_id]));
}
return $response;
}
}
3. Triggering the Modal
To launch the modal from a controller or form, build a link using the MediaLibraryState. Setting media_library_remaining to 1 enforces the single-item limit.
use Drupal\Core\Url;
use Drupal\media_library\MediaLibraryState;
// Create the state for our custom opener
$state = MediaLibraryState::create(
'your_module.heritage_opener', // Our service ID
['image', 'document'], // Allowed types
'image', // Default tab
1 // Quantity limit (1 for single asset)
);
$build['select_button'] = [
'#type' => 'link',
'#title' => $this->t('Select Heritage Asset'),
'#url' => Url::fromRoute('media_library.ui', [], ['query' => $state->all()]),
'#attributes' => [
'class' => ['use-ajax', 'button'],
'data-dialog-type' => 'modal',
'data-dialog-options' => json_encode(['width' => '80%']),
],
'#attached' => ['library' => ['core/drupal.dialog.ajax']],
];
4. Required HTML Placeholders
Ensure your template or form contains these matching IDs:
id="asset-preview-container": Where the thumbnail will appear.id="selected-asset-id": A hidden input to store the ID for the backend.
Configuration: Custom View Mode
To ensure the selected heritage asset matches the project's design, we use a dedicated view mode instead of the generic library thumbnail.
1. UI Configuration Steps
- Go to Structure > Display modes > View modes and add a new "Media" mode named Template:code.
- Navigate to Structure > Media types > [Your Type] > Manage display.
- Enable the Template:code under Custom display settings.
- Configure the layout:
- Hide all fields except the main file/image.
- Set the Format to Thumbnail and select a custom Image Style (e.g., Template:code).
2. Code Implementation
Update the Template:code method in Template:code to call this specific mode:
// Render the media using our project-specific view mode
$render_array = $view_builder->view($media, 'heritage_asset_preview');
3. CSS Styling
You can now target this specific preview in your theme:
.heritage-thumbnail-wrapper [data-drupal-view-mode="heritage_asset_preview"] {
border: 2px solid #a39161; /* Heritage gold border */
box-shadow: 3px 3px 10px rgba(0,0,0,0.2);
max-width: 300px;
}