Last active
March 1, 2022 03:06
-
-
Save jennatollerson/fcd5177476b6c7ab92ca1e3c1140be9c to your computer and use it in GitHub Desktop.
Drupal Form API, add an image field that includes a preview and an alt text field to your custom module's configuration form.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// src/Form/SettingsForm.php | |
/* Include theses dependencies in my_custom_module.info.yml | |
dependencies: | |
- drupal:file | |
- drupal:image | |
*/ | |
namespace Drupal\my_custom_module\Form; | |
use Drupal\Core\Form\ConfigFormBase; | |
use Drupal\Core\Form\FormStateInterface; | |
use Drupal\Core\Security\TrustedCallbackInterface; | |
use Drupal\file\Element\ManagedFile; | |
use Drupal\file\Entity\File; | |
/** | |
* Configure My Custom Module's settings for this site. | |
*/ | |
class SettingsForm extends ConfigFormBase implements TrustedCallbackInterface { | |
/** | |
* {@inheritdoc} | |
*/ | |
public function getFormId() { | |
return 'my_custom_module_settings'; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
protected function getEditableConfigNames() { | |
return ['my_custom_module.settings']; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function buildForm(array $form, FormStateInterface $form_state) { | |
$config = $this->config('my_custom_module.settings'); | |
$form['general'] = [ | |
'#type' => 'details', | |
'#title' => $this->t('Sitewide settings'), | |
'#collapsible' => TRUE, | |
'#open' => TRUE, | |
]; | |
// Add a managed file form element for uploading an image. | |
$form['general']['my_custom_module_image'] = [ | |
'#type' => 'managed_file', | |
'#title' => t('Image'), | |
'#description_display' => 'before', | |
'#upload_location' => 'public://', | |
'#upload_validators' => [ | |
'file_validate_extensions' => ['gif png jpg jpeg'], | |
'file_validate_is_image' => [], | |
], | |
'#process' => ['::processImage'], | |
'#theme' => 'image_widget', | |
'#default_value' => $config->get('my_custom_module_image'), | |
]; | |
$form['general']['my_custom_module_image']['alt'] = [ | |
'#type' => 'textfield', | |
'#title' => t('Alternative text'), | |
'#maxlength' => 512, | |
// If we don't bust this element out of the tree, it doesn't appear at all | |
// in $form_state after submission. I cannot figure out why. | |
'#tree' => FALSE, | |
'#default_value' => $config->get('my_custom_module_image_alt'), | |
]; | |
return parent::buildForm($form, $form_state); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function submitForm(array &$form, FormStateInterface $form_state) { | |
// First, set image file to permanent so Drupal doesn't try to clean it up. | |
if (!empty($form_state->getValue('my_custom_module_image'))) { | |
$fid = reset($form_state->getValue('my_custom_module_image')); | |
$file = File::load($fid); | |
$file->setPermanent(); | |
$file->save(); | |
} | |
$this->config('my_custom_module.settings') | |
->set('my_custom_module_image', $form_state->getValue('my_custom_module_image')) | |
->set('my_custom_module_image_alt', $form_state->getValue('alt')) | |
->save(); | |
parent::submitForm($form, $form_state); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public static function trustedCallbacks() { | |
return [ | |
'processImage', | |
'preRenderImage', | |
]; | |
} | |
/** | |
* Tweak the Image field with a #process callback. | |
*/ | |
public function processImage($element, &$form_state, $form) { | |
$element = ManagedFile::processManagedFile($element, $form_state, $form); | |
// If we remove the image, make sure the custom alt text goes away too. | |
if (empty($element['#value']['fids'])) { | |
$element['alt']['#default_value'] = NULL; | |
} | |
$element['#pre_render'][] = [SettingsForm::class, 'preRenderImage']; | |
return $element; | |
} | |
/** | |
* If an image is uploaded, show an image preview and an alt text field. | |
*/ | |
public static function preRenderImage(array $element) { | |
// If a custom image's been uploaded. | |
if (!empty($element['#value']['fids'])) { | |
// There's only ever going to be one file here. | |
$fid = reset($element['#value']['fids']); | |
$file = File::load($fid); | |
$image = \Drupal::service('image.factory')->get($file->getFileUri()); | |
// This will add preview of image at full size. | |
// If your image is not small you likely want to use | |
// '#theme' => 'image_style', | |
// '#style_name' => 'thumbnail', // choose an existing style. | |
$element['preview'] = [ | |
'#theme' => 'image', | |
'#uri' => $image->getSource(), | |
'#alt' => $file->getFilename(), | |
'#height' => $image->getHeight(), | |
'#width' => $image->getWidth(), | |
]; | |
} | |
else { | |
// If there's no file uploaded, hide the Alt text field. | |
$element['alt'] = [ | |
'#access' => FALSE, | |
]; | |
} | |
return $element; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment