I’m developing a custom Drupal module to add a new form element to the Webform module, which allows users to assign a score to each option in a radio button field. I’m new to Drupal development and would appreciate any guidance on what I might be doing wrong. Objective:
To create a custom Webform element where each radio option can have an additional score input field. Here is the code for webform_custom_choice.module:
<?php
/**
* Implements hook_webform_element_info_alter().
*/
function webform_custom_choice_webform_element_info_alter(array &$element_info) {
$element_info['choice_with_score'] = [
'class' => 'Drupal\webform_custom_choice\Plugin\WebformElement\ChoiceWithScore',
'label' => t('Choice with Score'),
'description' => t('Adds a radio button with an extra score field per option.'),
];
}
/**
* Implements hook_webform_element_presave().
*/
function webform_custom_choice_webform_element_presave(&$element) {
if (isset($element['#score'])) {
foreach ($element['#options'] as $key => &$option) {
$element['#score'][$key] = $element['#score'][$key] ?? 0;
}
}
}
/**
* Implements hook_webform_submission_presave().
*/
function webform_custom_choice_webform_submission_presave(\Drupal\webform\Entity\WebformSubmission $webform_submission) {
$data = $webform_submission->getData();
if (isset($data['choice_with_score'])) {
$choice_value = $data['choice_with_score'];
$element = $webform_submission->getWebform()->getElement('choice_with_score');
$score = isset($element['#score'][$choice_value]) ? $element['#score'][$choice_value] : 0;
$data['choice_with_score'] = ['value' => $choice_value, 'score' => $score];
$webform_submission->setData($data);
}
}
Here is the code for ChoiceWithScore.php:
php
<?php
namespace Drupal\webform_custom_choice\Plugin\WebformElement;
use Drupal\webform\Plugin\WebformElement\Radios;
use Drupal\Core\Form\FormStateInterface;
/**
* Provides a 'choice_with_score' element.
*
* @WebformElement(
* id = "choice_with_score",
* label = @Translation("Choice with Score"),
* description = @Translation("Provides a radio button element with an additional score field for each option."),
* category = @Translation("Choices"),
* )
*/
class ChoiceWithScore extends Radios {
/**
* {@inheritdoc}
*/
public function prepare(array &$element, ?\Drupal\webform\WebformSubmissionInterface $webform_submission = null) {
parent::prepare($element, $webform_submission);
if (isset($element['#options'])) {
foreach ($element['#options'] as $key => &$value) {
if (isset($element['#score'][$key])) {
$value .= ' (Score: ' . $element['#score'][$key] . ')';
} else {
$element['#score'][$key] = 0;
}
}
}
}
/**
* {@inheritdoc}
*/
public function getDefaultProperties() {
$properties = parent::getDefaultProperties();
$properties['states_wrapper'] = [];
$properties['id'] = 'choice_with_score';
$properties['composite'] = FALSE;
$properties['multiline'] = FALSE;
$properties['score'] = [];
return $properties;
}
/**
* {@inheritdoc}
*/
public function settingsForm(array $form, FormStateInterface $form_state, array $complete_form) {
$form = parent::settingsForm($form, $form_state, $complete_form);
$options = $form_state->getValue(['properties', 'options']) ?: $this->getElementOptions();
$scores = $form_state->getValue(['properties', 'score']) ?: $this->getElementScore();
foreach ($options as $key => $label) {
$form['score'][$key] = [
'#type' => 'number',
'#title' => $this->t('Score for @option', ['@option' => $label]),
'#default_value' => isset($scores[$key]) ? $scores[$key] : 0,
'#description' => $this->t('Specify a score for this option.'),
];
}
return $form;
}
/**
* Helper function to get scores for each option.
*/
private function getElementScore() {
return $this->getElementProperty('score', []);
}
}
Issues:
- I can’t see the extra score input fields when creating a webform.
- When I test the form, the question doesn’t display, and when I submit the form, I can only see the selected option without the score.
What I might be missing or doing wrong?