0

I have module that is currently setup like this

module
  -signature.module
  -signature.info.yml
  -src
    -Plugin
      -Field
        -FieldWiget
          -SignatureWidget.php
  -templates
    -signature.html.twig

Everything in the module works correctly as is. I'm trying to pass a variable $field_name = $items->getName(); from SignatureWidget.php to signature.html.twig (or signature.module so that I can then pass it to signature.html.twig). I'm trying to do this in order to apply ids generated from a variable in the widget to some of the markup in the template. How would one do this?

I understand how to do this from the .module file (Use a twig template instead of a render array in a custom module admin page), but can't seem to figure it out when it comes to plugin variables. The hook_theme in module associated with the widget looks like this.

function signature_theme() {

  $theme = [];
  $theme['signature'] = [
    'render element' => 'element',
    'variables' => array('sign_src' => ''),
  ];
  return $theme;
}

The widget code from SignatureWidget.php looks like this

<?php

namespace Drupal\signature\Plugin\Field\FieldWidget;

use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\WidgetBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\Render\ElementInfoManagerInterface;

/**
 * Plugin implementation of the 'field_signature_widget' widget.
 *
 * @FieldWidget(
 *   id = "field_signature_widget",
 *   module = "signature",
 *   label = @Translation("Signature Data"),
 *   field_types = {
 *     "field_signature"
 *   }
 * )
 */
class SignatureWidget extends WidgetBase {

  /**
   * {@inheritdoc}
   */
  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {

    $value = isset($items[$delta]->value) ? $items[$delta]->value : '';


    $file_upload_help = array(
        '#theme' => 'signature',
        '#sign_src' => $value,
      );
     $sign_thumb = array( '#type'   => 'html_tag',
                          '#tag' => 'img',
                          '#attributes' => array('src' => '', 'id' => 'signature_thumb', 'class'=>array('align-right'), 'width' =>'120px', 'height' => '60px' ));

$field_name = $items->getName();

    /*function getFieldName() {
      return $field_name;
    }*/

$text_area_id = 'signature_field_' . $field_name;  



    $element += array(
      '#type' => 'textarea',
      '#default_value' => $value,
      '#attributes' => array(
        'id' => array('signature_data'),
                        ),
      '#attached' => array(
        'library' => array('signature/signature_pad'),
                        ),
    );
    $element['#attached']['library'][] = 'signature/signature_pad';
    $element['#description'] = \Drupal::service('renderer')->renderPlain($file_upload_help);
    $element['#suffix'] = \Drupal::service('renderer')->renderPlain($sign_thumb);

    return array('value' => $element);
  }

}

The template from signature.html.twig looks like this.

<div class="signature">
    <canvas width="450" height="200" class="sign-canvas">SIGNATURE CANVAS</canvas>
{% if(sign_src != '') %}
    <img src = {{sign_src}} class="sign-img"></img>
{% endif %}
     <button type="button" id="clear-sign" class="button clear" data-action="clear">Clear</button>
</div>

I'm trying to return the string value from $text_area_id in SignatureWidget.php from within signature.html.twig

  • It's still not completely clear to me what you're trying to do. What is your template used for? Is it used as theming wrapper for your widget form? Please add your relevant hook_theme() part, how you try to wrap your form, and probably your relevant template parts. This would make it easier to understand what you want to do and giving you a to-the-point answer without having to read through other questions/answers you posted as reference. – Mario Steinitz Aug 23 '18 at 0:51
  • Thanks for letting me know! I have updated the question with what I'm hoping is all pertinent information. If you need anything else please let me know. I really appreciate your time. – Shawn Matthews Aug 23 '18 at 3:56
  • That made it far easier to understand. Please see my answer below. – Mario Steinitz Aug 23 '18 at 6:04
2

You already pass the template variable sign_src to your template. Now you want to pass an additional variable. You can easily do this by extending your hook_theme implementation:

/**
 * Implements hook_theme().
 */
function signature_theme() {
  $theme = [];
  $theme['signature'] = [
    'render element' => 'element',
    'variables' => [
      'sign_src' => NULL,
      'text_area_id' => NULL,
    ],
  ];
  return $theme;
}

Then pass the ID into your template like this:

$value = $items[$delta]->value ?: '';
$text_area_id = 'signature_field_' . $items->getName();

$file_upload_help = [
  '#theme' => 'signature',
  '#sign_src' => $value,
  '#text_area_id' => $text_area_id,
];

And use it in your template like this:

{{ text_area_id }}

Edit: Some further suggestions for your code snippets:

Wherever possible, you should leave rendering to the theming engine and avoid manually calling the \Drupal::service('renderer')->renderPlain() method. Your description will do just fine with the render array. Your #suffix can be changed to a distinct child element of your widget element (note: there is no hash before):

$element['#description'] = $file_upload_help;
$element['suffix'] = $sign_thumb;

In your template, you can change the empty check to

{% if sign_src %}
  <img src="{{sign_src}}" class="sign-img" />
{% endif %}

And should wrap the src URL into quotes.

A final note about the URL itself: It seems to be a user given value. If so, consider using UrlHelper::stripDangerousProtocols before you pass it into the template.

  • Thank you Mario. That makes perfect sense. I had thought I had tried something just like that. Your setup works perfectly many thanks. – Shawn Matthews Aug 23 '18 at 16:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.