Formular-API-Bildvorschau

6

Ich habe viele Diskussionen über die Bildvorschau in fapi mit gelesen 'managed_file', aber ich kann keine schlüssige Antwort darauf finden, wie dies in D8 richtig gemacht wird.

Eine naheliegende Lösung wäre die Wiederverwendung Drupal\image\Plugin\Field\FieldWidget\ImageWidget, aber ich weiß nicht, wie ich das erreichen soll.

Meine Frage lautet also: Wie kann ich in D8 ein Bild-Upload-Feld mit Bildvorschau in meinem Formular haben und wie würde das assoziative Array in meiner buildFormFunktion aussehen?

maartend
quelle

Antworten:

9

Nachdem ich eine Weile gesucht habe, habe ich hier eine Problemumgehungslösung gefunden: https://stackoverflow.com/a/38268567/2267244

Ich habe es getestet und es funktioniert, hier ist eine etwas modifizierte Version, die ich verwendet habe.

Ich bin mir auch nicht sicher, ob wir diese Frage als dpulicate markieren sollen, da ich die Lösung auf stackoverflow.com gefunden habe.

Wie auch immer: So sollte Ihr Formularfeld aussehen:

$form['image_with_preview'] = [
  '#type' => 'managed_file',
  '#title' => t('Image with preview'),
  '#upload_validators' => [
    'file_validate_extensions' => ['gif png jpg jpeg'],
    'file_validate_size' => [25600000],
  ],
  '#theme' => 'image_widget',
  '#preview_image_style' => 'medium',
  '#upload_location' => 'public://',
  '#required' => FALSE,
];

Und außerdem müssen Sie hook_preprocess_HOOKin Ihrem Modul Folgendes implementieren :

function YOUR_MODULE_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 (\Drupal\Core\Render\Element::children($element) as $child) {
      $variables['data'][$child] = $element[$child];
    }
}

Ich habe es auf meiner lokalen Drupal-Instanz getestet und es funktioniert einwandfrei. Die Bildvorschau wurde angezeigt, nachdem der AJAX-Upload abgeschlossen war.

Otarza
quelle