#StackBounty: #8 #javascript Why does JavaScript attached in a widgets render array return the variable value from only the first widge…

Bounty: 50

I have a custom field type called signature_field. It invokes a JS file and has its own custom template. I pass a variable to both the JS file and template called $text_area_id. In Drupal if I add multiple fields on the same node with my custom signature_field type my variable is correctly passed to the template for each of the various fields. The JavaScriot code, however, returns only the ID fo the first field added for each of the subsequent fields.

I pass $text_area_id using the following code from the SignatureWidget.php file of a custom module to both the JavaScript code and the template.

namespace Drupalsignature_fieldPluginFieldFieldWidget;

use DrupalCoreFieldFieldItemListInterface;
use DrupalCoreFieldWidgetBase;
use DrupalCoreFormFormStateInterface;
use DrupalCoreRenderElement;
use DrupalCoreRenderElementInfoManagerInterface;

/**
 * Plugin implementation of the 'field_signature_field_widget' widget.
 *
 * @FieldWidget(
 *   id = "field_signature_field_widget",
 *   module = "signature_field",
 *   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 : '';

     // 
     //$sign_thumb = array( '#type'   => 'html_tag',
     //                     '#tag' => 'img',
     //                     '#attributes' => array('src' => '', 'id' => 'signature_thumb_test', 'class'=>array('align-right'), 'width' =>'120px', 'height' => '60px' ));

    $field_name = $items->getName();

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

    $text_area_id = 'signature_field_' . $field_name;  

    $file_upload_help = array(
      '#theme' => 'signature',
      '#sign_src' => $value,
      '#text_area_id' => $text_area_id,
    );

    $element += array(
      '#type' => 'textarea',
      '#default_value' => $value,  
      '#attributes' => array(
        'id' => array($text_area_id),
                        ),
      '#attached' => array(
        'library' => array('signature_field/signature_pad'),
                        ),
    );
    $element['#attached']['library'][] = 'signature_field/signature_pad';
    $element['#description'] = Drupal::service('renderer')->renderPlain($file_upload_help);
    $element['#attached']['drupalSettings']['signature_field']['sign']['id'] = $text_area_id;

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

}

The template code is the following one.

{{text_area_id}} SIGNATURE CANVAS {% if(sign_src != '') %} {% endif %}

It correctly returns different values based on the field name for each of the fields on the given node. The JavaScript code is the following.

(function ($, window, Drupal, drupalSettings) {

    Drupal.behaviors.signature = {
        attach: function (context, settings) {

            var canvasId = drupalSettings.signature_field.sign.id;
            console.log(canvasId);

            var canvas = document.querySelector('#' + canvasId + "_canvas");
            var signaturePad = new SignaturePad(canvas, {
                minWidth: 0.5,
                maxWidth: 2.5,
                backgroundColor: "rgb(250, 250, 250)",
                penColor: "rgb(66, 133, 244)",
                onEnd:function(){
                    $('#' + canvasId).val(signaturePad.toDataURL());
                }
            });

            $('#' + canvasId).hide();
            $('#' + canvasId + '_clear_sign').click(function(){
                var signaturePad;
                var canvas = document.querySelector('#' + canvasId + "_canvas");
                signaturePad = new SignaturePad(canvas,{
                 penColor: "rgb(66, 133, 244)",
                });
                signaturePad.clear();
                $('#' + canvasId).val('');
            });
            if ($('#' + canvasId + "_image").attr('src')) {
                $('#' + canvasId + "_canvas").hide();
                $('#' + canvasId + '_clear_sign').addClass('chnge-canvas');
            }
            if ($('#' + canvasId + '_clear_sign' + '.chnge-canvas').length) {
                $('#' + canvasId + '_clear_sign' + '.chnge-canvas').click(function(){
                    $('#' + canvasId + '_clear_sign').removeClass('chnge-canvas');
                    $('#' + canvasId + "_image").hide().attr({ 'src':''});
                    $('#' + canvasId + "_canvas").show();
                });
            }

        },
        detach: function (context) {

        }
    };

})(jQuery, this, Drupal, drupalSettings);

The console log –

var canvasId = drupalSettings.signature_field.sign.id;
                console.log(canvasId);

It returns the field name for only the first value of the widget added from the node. It returns it multiple times based on how many times the custom field_type is invoked. How can I get the id for each of the fields in JavaScript? Why does this work different in the template and the JavaScript code?


Get this bounty!!!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.