0

On my Drupal 8 dev instance (Acquia, PHP 7.315, Windows 10) I have the WebForm module installed. I want to add a custom element, like modules\webform\modules\webform_example_element. I have successfully installed the default webform_example_element and this element can be added to a webform using the webform UI.

I have created a copy of the webform_example_element in modules\custom\my_webform_example_element and changed webform_example_element to my_webform_example_element in the PHP and YAML files. I have successfully installed the my_webform_example_element module using Drupal extend (no errors in the drupal log), but the my_webform_example_element doesn't show up in the webform UI.

Is there something extra that must be done to use custom elements from the module\custom directory?

These are the files I used and their content.

my_webform_example_element.info.yml

name: 'My Webform Element Example'
type: module
description: 'My: Provides an example that shows how to create a Webform element.'
package: 'Webform example'
core_version_requirement: ^8.8
dependencies:
  - 'webform:webform'

# Information added by Drupal.org packaging script on 2021-02-04
version: '8.x-5.24'
project: 'webform'
datestamp: 1612453182

config/install/webform.webform.my_webform_example_element.yml

uuid: null
langcode: en
status: open
dependencies:
  enforced:
    module:
      - my_webform_example_element
open: null
close: null
weight: 0
uid: null
template: false
archive: false
id: my_webform_example_element
title: 'Example: My Webform Element'
description: 'MY example of a custom Webform element.'
category: Example
elements: |
  my_webform_example_element:
    '#type': my_webform_example_element
    '#title': 'My Webform Example Element'
  my_webform_example_element_multiple:
    '#type': my_webform_example_element
    '#title': 'My Webform Example Element Multiple'
    '#multiple': true
  
css: ''
javascript: ''
settings:
  ajax: false
  ajax_scroll_top: form
  ajax_progress_type: ''
  ajax_effect: ''
  ajax_speed: null
  page: true
  page_submit_path: ''
  page_confirm_path: ''
  page_theme_name: ''
  form_title: source_entity_webform
  form_submit_once: false
  form_exception_message: ''
  form_open_message: ''
  form_close_message: ''
  form_previous_submissions: true
  form_confidential: false
  form_confidential_message: ''
  form_remote_addr: true
  form_convert_anonymous: false
  form_prepopulate: false
  form_prepopulate_source_entity: false
  form_prepopulate_source_entity_required: false
  form_prepopulate_source_entity_type: ''
  form_reset: false
  form_disable_autocomplete: false
  form_novalidate: false
  form_disable_inline_errors: false
  form_required: false
  form_unsaved: false
  form_disable_back: false
  form_submit_back: false
  form_autofocus: false
  form_details_toggle: false
  form_access_denied: default
  form_access_denied_title: ''
  form_access_denied_message: ''
  form_access_denied_attributes: {  }
  form_file_limit: ''
  share: false
  share_node: false
  share_theme_name: ''
  share_title: true
  share_page_body_attributes: {  }
  submission_label: ''
  submission_log: false
  submission_views: {  }
  submission_views_replace: {  }
  submission_user_columns: {  }
  submission_user_duplicate: false
  submission_access_denied: default
  submission_access_denied_title: ''
  submission_access_denied_message: ''
  submission_access_denied_attributes: {  }
  submission_exception_message: ''
  submission_locked_message: ''
  submission_excluded_elements: {  }
  submission_exclude_empty: false
  submission_exclude_empty_checkbox: false
  previous_submission_message: ''
  previous_submissions_message: ''
  autofill: false
  autofill_message: ''
  autofill_excluded_elements: {  }
  wizard_progress_bar: true
  wizard_progress_pages: false
  wizard_progress_percentage: false
  wizard_progress_link: false
  wizard_progress_states: false
  wizard_auto_forward: true
  wizard_auto_forward_hide_next_button: false
  wizard_keyboard: true
  wizard_start_label: ''
  wizard_preview_link: false
  wizard_confirmation: true
  wizard_confirmation_label: ''
  wizard_track: ''
  wizard_prev_button_label: ''
  wizard_next_button_label: ''
  wizard_toggle: false
  wizard_toggle_show_label: ''
  wizard_toggle_hide_label: ''
  preview: 1
  preview_label: ''
  preview_title: ''
  preview_message: ''
  preview_attributes: {  }
  preview_excluded_elements: {  }
  preview_exclude_empty: true
  preview_exclude_empty_checkbox: false
  draft: none
  draft_multiple: false
  draft_auto_save: false
  draft_saved_message: ''
  draft_loaded_message: ''
  draft_pending_single_message: ''
  draft_pending_multiple_message: ''
  confirmation_type: page
  confirmation_title: ''
  confirmation_message: ''
  confirmation_url: ''
  confirmation_attributes: {  }
  confirmation_back: true
  confirmation_back_label: ''
  confirmation_back_attributes: {  }
  confirmation_exclude_query: false
  confirmation_exclude_token: false
  confirmation_update: false
  limit_total: null
  limit_total_interval: null
  limit_total_message: ''
  limit_total_unique: false
  limit_user: null
  limit_user_interval: null
  limit_user_message: ''
  limit_user_unique: false
  entity_limit_total: null
  entity_limit_total_interval: null
  entity_limit_user: null
  entity_limit_user_interval: null
  purge: none
  purge_days: null
  results_disabled: false
  results_disabled_ignore: false
  results_customize: false
  token_view: false
  token_update: false
  token_delete: false
  serial_disabled: false
access:
  create:
    roles:
      - anonymous
      - authenticated
    users: {  }
    permissions: {  }
  view_any:
    roles: {  }
    users: {  }
    permissions: {  }
  update_any:
    roles: {  }
    users: {  }
    permissions: {  }
  delete_any:
    roles: {  }
    users: {  }
    permissions: {  }
  purge_any:
    roles: {  }
    users: {  }
    permissions: {  }
  view_own:
    roles: {  }
    users: {  }
    permissions: {  }
  update_own:
    roles: {  }
    users: {  }
    permissions: {  }
  delete_own:
    roles: {  }
    users: {  }
    permissions: {  }
  administer:
    roles: {  }
    users: {  }
    permissions: {  }
  test:
    roles: {  }
    users: {  }
    permissions: {  }
  configuration:
    roles: {  }
    users: {  }
    permissions: {  }
handlers: {  }
variants: {  }

src/Element/MyWebformExampleElement.php

namespace Drupal\my_webform_example_element\Element;

use Drupal\Core\Render\Element;
use Drupal\Core\Render\Element\FormElement;
use Drupal\Core\Form\FormStateInterface;

/**
 * Provides a 'my_webform_example_element'.
 *
 * Webform elements are just wrappers around form elements, therefore every
 * webform element must have correspond FormElement.
 *
 * Below is the definition for a custom 'my_webform_example_element' which just
 * renders a simple text field.
 *
 * @FormElement("my_webform_example_element")
 *
 * @see \Drupal\Core\Render\Element\FormElement
 * @see https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Render%21Element%21FormElement.php/class/FormElement
 * @see \Drupal\Core\Render\Element\RenderElement
 * @see https://api.drupal.org/api/drupal/namespace/Drupal%21Core%21Render%21Element
 * @see \Drupal\my_webform_example_element\Element\MyWebformExampleElement
 */
class MyWebformExampleElement extends FormElement {

  /**
   * {@inheritdoc}
   */
  public function getInfo() {
    $class = get_class($this);
    return [
      '#input' => TRUE,
      '#size' => 60,
      '#process' => [
        [$class, 'processWebformElementExample'],
        [$class, 'processAjaxForm'],
      ],
      '#element_validate' => [
        [$class, 'validateMyWebformExampleElement'],
      ],
      '#pre_render' => [
        [$class, 'preRenderMyWebformExampleElement'],
      ],
      '#theme' => 'input__my_webform_example_element',
      '#theme_wrappers' => ['form_element'],
    ];
  }

  /**
   * Processes a 'my_webform_example_element' element.
   */
  public static function processWebformElementExample(&$element, FormStateInterface $form_state, &$complete_form) {
    // Here you can add and manipulate your element's properties and callbacks.
    return $element;
  }

  /**
   * Webform element validation handler for #type 'my_webform_example_element'.
   */
  public static function validateMyWebformExampleElement(&$element, FormStateInterface $form_state, &$complete_form) {
    // Here you can add custom validation logic.
  }

  /**
   * Prepares a #type 'email_multiple' render element for theme_element().
   *
   * @param array $element
   *   An associative array containing the properties of the element.
   *   Properties used: #title, #value, #description, #size, #maxlength,
   *   #placeholder, #required, #attributes.
   *
   * @return array
   *   The $element with prepared variables ready for theme_element().
   */
  public static function preRenderMyWebformExampleElement(array $element) {
    $element['#attributes']['type'] = 'text';
    Element::setAttributes($element, ['id', 'name', 'value', 'size', 'maxlength', 'placeholder']);
    static::setAttributes($element, ['form-text', 'my-webform-example-element']);
    return $element;
  }

}

Plugin/MyWebformElement/MyWebformExampleElement.php

namespace Drupal\my_webform_example_element\Plugin\WebformElement;

use Drupal\Core\Form\FormStateInterface;
use Drupal\webform\Plugin\WebformElementBase;
use Drupal\webform\WebformSubmissionInterface;

/**
 * Provides a 'my_webform_example_element' element.
 *
 * @WebformElement(
 *   id = "my_webform_example_element",
 *   label = @Translation("My Webform example element"),
 *   description = @Translation("Provides MY webform element example."),
 *   category = @Translation("Example elements"),
 * )
 *
 * @see \Drupal\my_webform_example_element\Element\MyWebformExampleElement
 * @see \Drupal\webform\Plugin\WebformElementBase
 * @see \Drupal\webform\Plugin\WebformElementInterface
 * @see \Drupal\webform\Annotation\WebformElement
 */
class MyWebformExampleElement extends WebformElementBase {

  /**
   * {@inheritdoc}
   */
  protected function defineDefaultProperties() {
    // Here you define your webform element's default properties,
    // which can be inherited.
    //
    // @see \Drupal\webform\Plugin\WebformElementBase::defaultProperties
    // @see \Drupal\webform\Plugin\WebformElementBase::defaultBaseProperties
    return [
      'multiple' => '',
      'size' => '',
      'minlength' => '',
      'maxlength' => '',
      'placeholder' => '',
    ] + parent::defineDefaultProperties();
  }

  /****************************************************************************/

  /**
   * {@inheritdoc}
   */
  public function prepare(array &$element, WebformSubmissionInterface $webform_submission = NULL) {
    parent::prepare($element, $webform_submission);

    // Here you can customize the webform element's properties.
    // You can also customize the form/render element's properties via the
    // FormElement.
    //
    // @see \Drupal\my_webform_example_element\Element\MyWebformExampleElement::processWebformElementExample
  }

  /**
   * {@inheritdoc}
   */
  public function form(array $form, FormStateInterface $form_state) {
    $form = parent::form($form, $form_state);
    // Here you can define and alter a webform element's properties UI.
    // Form element property visibility and default values are defined via
    // ::defaultProperties.
    //
    // @see \Drupal\webform\Plugin\WebformElementBase::form
    // @see \Drupal\webform\Plugin\WebformElement\TextBase::form
    return $form;
  }

}
4
  • 1
    Did you update all the namespace namespace Drupal\MY_MODULE\Plugin\WebformElement;? Did you update the ID inside the annotation in front of the class? /** @WebformElement( id = "MY_CUSTOM_UNIQUE_ID",... ? (This does look like a comment, but it is actually an annotation and is part of the code) - Rebuilt the cache after doing code change there – Hudri Feb 22 at 8:54
  • Welcome to Drupal Answers! Since you renamed at least a file, we need to see the code you wrote, or we cannot answer on what's wrong in that code. I would check what @Hudri suggested, to start. – kiamlaluno Feb 22 at 9:11
  • @Hudri: yes, I have updated the id and the namespaces.I've updated the question with my modified files. – Peter Feb 22 at 9:26
  • This issue is resolved. Turned out that the provided code worked without problems on a clean Drupal 8 instance. After removing several failed modules from the original dev Drupal 8 instance and re-enabling only this custom element everything is working fine now. – Peter Feb 25 at 8:07

Your Answer

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

Browse other questions tagged or ask your own question.