Score:-2

Custom textfield element, different $form_state value and element '#value' value

cn flag

I have a textfield element (named 'bus_station'), which holds a bus station name.

I am looking for a way to create a custom 'bus_station' element (possibly extending Textfield class), which would:

  • Still expect a text input in form of bus station name (and retain it during $form_state->setRebuild() and show it to user), but
  • In $form_value, after form submit, either provide a FALSE (custom code in Element definition doesn't recognize input as a station) or TRUE (it does recognize a station)? Or Entity ID (ID of a matched bus station) and/or NULL (no match)?
Score:0
cn flag

This can be done via Form API callback implementation:

Inside module/src/Element/ElementClass.php, in public function getInfo() {} define a callback, e.g. processMyElement under '#process' key:

public function getInfo() {
  $class = static::class;
  return [
    // [...] Some other definitions.
    '#process' => [
      [$class, 'processMyElement'],
    ],
  ];
}

And then perform two complementary operations.

(1) Process the user input and return a value which will be provided in the '#form_state' values in valueCallback() method:

public static function valueCallback(&$element, $input, FormStateInterface $form_state) {
  $output = parent::valueCallback($element, $input, $form_state);
  if ($input == 'SOMETHING') {
    $output = 'SOMETHING_ELSE';
  }
  return $output;
}

(2) And vice versa, in the processMyElement() method return the original value:

public static function processMyElement(&$element, FormStateInterface $form_state, &$complete_form) {
  if ($element['#value'] == 'SOMETHING_ELSE') {
    $element['#value'] = 'SOMETHING';
  }
  return $element;
}

Usage example

I have used this to extend Drupal\Core\Render\Element\Textfield class in combination with JS Storage Complete. That gives me Autocomplete (without need for a callback URL). This autocomplete returns Entity ID obtained via entity load based on unique label inside valueCallback() method, but user is still presented with its text input (obtained by returning $entity->label() inside processMyElement() method).

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.