6

I have managed_file for uploading an image in my form and I would like to display the image(thumbnail) right away when the user uploads it so he won' have to submit the form to see it(I am rendering it in the form if the image exists).

I think there might be an issue with the ajax wrapper/structure so I am not sure how exactly it should be achieved without too much customization/coding.

2

1 Answer 1

7

This is my solution:

<?php

namespace Drupal\foo\Element;

use Drupal\Core\Form\FormStateInterface;
use Drupal\file\Element\ManagedFile;

/**
 * @FormElement("managed_image")
 */
class ManagedImage extends ManagedFile {

  /**
   * {@inheritdoc}
   */
  public function getInfo() {
    $info = parent::getInfo();
    // @see \Drupal\image\Plugin\Field\FieldWidget\ImageWidget::formElement()
    $info['#accept'] = 'image/*';
    $info['#image_style'] = 'thumbnail';

    return $info;
  }

  /**
   * {@inheritdoc}
   */
  public static function processManagedFile(&$element, FormStateInterface $form_state, &$complete_form) {
    /** @var \Drupal\Core\Image\ImageFactory $image_factory */
    $image_factory = \Drupal::service('image.factory');
    $element['#upload_validators'] += [
      'file_validate_is_image' => [],
      'file_validate_extensions' => [implode(' ', $image_factory->getSupportedExtensions())]
    ];

    $element['#description'] = [
      '#theme' => 'file_upload_help',
      '#description' => isset($element['#description']) ? $element['#description'] : NULL,
      '#upload_validators' => $element['#upload_validators']
    ];

    return parent::processManagedFile($element, $form_state, $complete_form);
  }

  /**
   * {@inheritdoc}
   */
  public static function preRenderManagedFile($element) {
    $element = parent::preRenderManagedFile($element);

    if (!empty($element['#files'])) {
      foreach ($element['#files'] AS $delta => $file) {
        /** @var \Drupal\file\Entity\File $file */
        $element['file_' . $delta] = [
          'preview' => [
            '#type' => 'container',
            '#weight' => -10,
            '#attributes' => [
              'class' => [
                'image-preview'
              ]
            ],
            'image' => [
              '#theme' => 'image_style',
              '#style_name' => $element['#image_style'],
              '#uri' => $file->getFileUri()
            ]
          ]
        ] + $element['file_' . $delta];
      }
    }

    return $element;
  }

}
1
  • 1
    Great solution, thank you for providing it. Please consider that while implementing this, also in Form Field definition should be changed to: '#type' => 'managed_image', .
    – Francis
    Apr 12, 2018 at 9:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.