Drupal 8, добавьте поле изображения из BuildForm с предварительным просмотром

Я создал пользовательскую форму из функции buildForm. В этой форме я хотел бы добавить поле изображения.

Я могу сделать это с помощью этого кода:

$form['main']['image'] = array(
    '#type' => 'text_format',
    '#title' => t('image'),
    '#default_value' => array(10),
);

Я могу загрузить и удалить изображение из моей формы. Однако, когда я загружаю изображение, у меня нет этого предварительного просмотра. Я имею в виду, когда я создаю контент через пользовательский интерфейс Drupal. Я могу добавить предварительно настроенное поле «изображение». Когда я загружаю изображение через это поле «изображение», у меня есть предварительный просмотр изображения.

И здесь, когда я создаю элемент поля программно, у меня нет предварительного просмотра изображения, когда я загружаю ее. Как использовать API Drupal для предварительного просмотра изображения, когда я загружаю ее через поле «изображение»?


person matthieu lopez    schedule 05.12.2015    source источник


Ответы (4)


Итак, вот как я получил свою форму для отображения миниатюры изображения. Что я в основном сделал, так это взял код в ImageWidget::process, поместил его в препроцессор темы и установил для свойства #theme элемента значение image_widget.

Ваш элемент изображения в классе формы должен выглядеть так:

$form['profile_image'] = [
   '#type' => 'managed_file',
   '#title' => t('Profile Picture'),
   '#upload_validators' => array(
       'file_validate_extensions' => array('gif png jpg jpeg'),
       'file_validate_size' => array(25600000),
   ),
   **'#theme' => 'image_widget',**
   **'#preview_image_style' => 'medium',**
   '#upload_location' => 'public://profile-pictures',
   '#required' => TRUE,
];

В вашем файле name_of_default_theme.theme вам нужно следующее:

function name_of_default_theme_preprocess_image_widget(&$variables) {
    $element = $variables['element'];

    $variables['attributes'] = array('class' => array('image-widget', 'js-form-managed-file', 'form-managed-file', 'clearfix'));

    if (!empty($element['fids']['#value'])) {
        $file = reset($element['#files']);
        $element['file_' . $file->id()]['filename']['#suffix'] = ' <span class="file-size">(' . format_size($file->getSize()) . ')</span> ';
        $file_variables = array(
            'style_name' => $element['#preview_image_style'],
            'uri' => $file->getFileUri(),
        );

        // Determine image dimensions.
        if (isset($element['#value']['width']) && isset($element['#value']['height'])) {
            $file_variables['width'] = $element['#value']['width'];
            $file_variables['height'] = $element['#value']['height'];
        } else {
            $image = \Drupal::service('image.factory')->get($file->getFileUri());
            if ($image->isValid()) {
                $file_variables['width'] = $image->getWidth();
                $file_variables['height'] = $image->getHeight();
            }
            else {
                $file_variables['width'] = $file_variables['height'] = NULL;
            }
        }

        $element['preview'] = array(
            '#weight' => -10,
            '#theme' => 'image_style',
            '#width' => $file_variables['width'],
            '#height' => $file_variables['height'],
            '#style_name' => $file_variables['style_name'],
            '#uri' => $file_variables['uri'],
        );

        // Store the dimensions in the form so the file doesn't have to be
        // accessed again. This is important for remote files.
        $element['width'] = array(
            '#type' => 'hidden',
            '#value' => $file_variables['width'],
        );
        $element['height'] = array(
            '#type' => 'hidden',
            '#value' => $file_variables['height'],
        );
    }

    $variables['data'] = array();
    foreach (Element::children($element) as $child) {
        $variables['data'][$child] = $element[$child];
    }
}

Решение работает хорошо, но в модуле изображения отсутствует класс с аннотацией @FormElement. Вот почему элемент не отображается должным образом.

person Je Suis Alrick    schedule 08.07.2016
comment
Есть ли способ заставить его работать с несколькими файлами? Я имею в виду, что когда вы добавляете '#multiple' => TRUE в управляемое поле, приведенный выше код показывает предварительный просмотр только для первого изображения. - person PolGraphic; 01.01.2017
comment
Я не уверен, но, учитывая набор файлов, может сработать что-то вроде этого: $element['preview'][n] = array('#theme', ...). - person Je Suis Alrick; 20.01.2017
comment
ПРИМЕЧАНИЕ. Используйте приведенную ниже функцию предварительной обработки для многих классов элементов в D8. Друпал\Ядро\Рендеринг\Элемент; - person user25794; 04.01.2019

Можете ли вы попробовать с типом manage_file?

'#type' => 'managed_file'
person Nish    schedule 01.02.2016

Хороший ответ, спасибо, единственное изменение, которое я бы сделал, это использовать токен для места загрузки и байты для размера загрузки файла, хотя я думаю, это зависит от варианта использования. Что-то вроде приведенного ниже (убрана большая часть кода для простоты.

namespace Drupal\my_module\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\Component\Utility\Bytes;
use Drupal\Core\Utility\Token;

class SampleForm extends FormBase
{

  protected $currentUser;

  protected $token;


  public function __construct(AccountProxyInterface $current_user, Token $token) {
    $this->currentUser = $current_user;
    $this->token = $token;
  }


  public static function create(ContainerInterface $container)
  {
    return new static(
      $container->get('current_user'),
      $container->get('token')
    );
  }


  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {

    $form['sample_image'] = [
        '#type' => 'managed_file',
        '#title' => t('Profile Picture'),
        '#upload_validators' => array(
          'file_validate_extensions' => array('gif png jpg jpeg'),
          'file_validate_size' => file_upload_max_size() / pow(Bytes::KILOBYTE, 2) . 'M',
        ),
      '#theme' => 'image_widget',
      '#preview_image_style' => 'medium',
      '#upload_location' => $this->token->replace('private://[date:custom:Y]-[date:custom:m]'),
      '#required' => TRUE,
    ];

    return $form;
  }
}
person user25794    schedule 03.01.2019
comment
Этот код дает мне поле формы, но не предварительный просмотр изображения после его загрузки. - person akalata; 26.03.2019

Тема для работы с загрузкой нескольких файлов. Из ответа @Je Suis Alrick выше.

    function themename_preprocess_image_widget(&$variables) {
    $element = $variables['element'];

    $variables['attributes'] = array('class' => array('image-widget', 'js-form-managed-file', 'form-managed-file', 'clearfix'));
   
    if (!empty($element['fids']['#value'])) {

        foreach ($element['#files'] as $file) {
         
            $element['file_' . $file->id()]['filename']['#suffix'] = ' <span class="file-size">(' . format_size($file->getSize()) . ')</span> ';
            $file_variables = array(
                'style_name' => $element['#preview_image_style'],
                'uri' => $file->getFileUri(),
            );

            // Determine image dimensions.
            if (isset($element['#value']['width']) && isset($element['#value']['height'])) {
                $file_variables['width'] = $element['#value']['width'];
                $file_variables['height'] = $element['#value']['height'];
            } else {
                $image = \Drupal::service('image.factory')->get($file->getFileUri());
                if ($image->isValid()) {
                    $file_variables['width'] = $image->getWidth();
                    $file_variables['height'] = $image->getHeight();
                }
                else {
                    $file_variables['width'] = $file_variables['height'] = NULL;
                }
            }

            $element['preview'][] = array(
                '#weight' => -10,
                '#theme' => 'image_style',
                '#width' => $file_variables['width'],
                '#height' => $file_variables['height'],
                '#style_name' => $file_variables['style_name'],
                '#uri' => $file_variables['uri'],
            );

            // Store the dimensions in the form so the file doesn't have to be
            // accessed again. This is important for remote files.
            $element['width'] = array(
                '#type' => 'hidden',
                '#value' => $file_variables['width'],
            );
            $element['height'] = array(
                '#type' => 'hidden',
                '#value' => $file_variables['height'],
            );
        }
    }


    $variables['data'] = array();
    foreach (\Drupal\Core\Render\Element::children($element) as $child) {
        $variables['data'][$child] = $element[$child];
    }
}
person fkaufusi    schedule 22.07.2021