0

I tried some variations on the code below, but I have not been able to pass my custom form options to render().

class CustomField extends FieldPluginBase {

  public function query() {
    // This is a custom field.
    // Leave empty to avoid a query on this field.
  }

  protected function defineOptions() {
    $options = parent::defineOptions();
    $options['my_options'] = [
      '1' => 1,
      '2' => 2,
      '3' => 3,
    ];
    return $options;
  }

  public function buildOptionsForm(&$form, FormStateInterface $form_state) {

    //Form select element.
    $form['my_options'] = [
      '#type' => 'select',
      '#required' => TRUE,
      '#title' => $this->t('My Options'),
      '#options' => $this->options['my_options'],
      '#description' => $this->t('Description.'),
      '#default_value' => 1,
    ];
    parent::buildOptionsForm($form, $form_state);
  }

  public function render(ResultRow $values) {
    return kpr($this->options['my_options']);
  }

}

As is the ['my_options'] key is empty. If I create the $options['my_options'] in buildOptionsForm() it does populate the select list in the views field form. Both, however, break the output of the render(ResultRow $values) function. No errors, just no output.

How do you create and pass options from defineOptions() to buildOptionsForm(), and inevitably access them in render(ResultRow $values)?

Trying to reference: FieldPluginBase::defineOptions and Field::buildOptionsForm without success. As well as referencing: https://www.webomelette.com/creating-custom-views-field-drupal-8

2 Answers 2

1

The defineOptions() method returns the view field options, not the options to use in one of the form elements returned from the buildOptionsForm() method.

If you look at an existing defineOptions() implementation, for example Date::defineOptions() or Custom::defineOptions(), you will notice the returned array follows a specific format.

protected function defineOptions() {
  $options = parent::defineOptions();
  $options['date_format'] = [
    'default' => 'small',
  ];
  $options['custom_date_format'] = [
    'default' => '',
  ];
  $options['timezone'] = [
    'default' => '',
  ];
  return $options;
}
protected function defineOptions() {
  $options = parent::defineOptions();

  // Override the alter text option to always alter the text.
  $options['alter']['contains']['alter_text'] = [
    'default' => TRUE,
  ];
  $options['hide_alter_empty'] = [
    'default' => FALSE,
  ];
  return $options;
}

The buildOptionsForm() method then uses the $this->options array to set the default values of the form elements it shows. (See Date::buildOptionsForm().)

public function buildOptionsForm(&$form, FormStateInterface $form_state) {
  $date_formats = [];
  foreach ($this->dateFormatStorage->loadMultiple() as $machine_name => $value) {
    $date_formats[$machine_name] = $this->t('@name format: @date', [
      '@name' => $value
        ->label(),
      '@date' => $this->dateFormatter->format(REQUEST_TIME, $machine_name),
    ]);
  }
  $form['date_format'] = [
    '#type' => 'select',
    '#title' => $this
      ->t('Date format'),
    '#options' => $date_formats + [
      'custom' => $this->t('Custom'),
      'raw time ago' => $this->t('Time ago'),
      'time ago' => $this->t('Time ago (with "ago" appended)'),
      'raw time hence' => $this->t('Time hence'),
      'time hence' => $this->t('Time hence (with "hence" appended)'),
      'raw time span' => $this->t('Time span (future dates have "-" prepended)'),
      'inverse time span' => $this->t('Time span (past dates have "-" prepended)'),
      'time span' => $this->t('Time span (with "ago/hence" appended)'),
    ],
    '#default_value' => isset($this->options['date_format']) ? $this->options['date_format'] : 'small',
  ];
  $form['custom_date_format'] = [
    '#type' => 'textfield',
    '#title' => $this->t('Custom date format'),
    '#description' => $this->t('If "Custom", see <a href="http://us.php.net/manual/en/function.date.php" target="_blank">the PHP docs</a> for date formats. Otherwise, enter the number of different time units to display, which defaults to 2.'),
    '#default_value' => isset($this->options['custom_date_format']) ? $this->options['custom_date_format'] : '',
  ];

  // Setup #states for all possible date_formats on the custom_date_format form element.
  foreach ([
    'custom',
    'raw time ago',
    'time ago',
    'raw time hence',
    'time hence',
    'raw time span',
    'time span',
    'raw time span',
    'inverse time span',
    'time span',
  ] as $custom_date_possible) {
    $form['custom_date_format']['#states']['visible'][] = [
      ':input[name="options[date_format]"]' => [
        'value' => $custom_date_possible,
      ],
    ];
  }
  $form['timezone'] = [
    '#type' => 'select',
    '#title' => $this->t('Timezone'),
    '#description' => $this->t('Timezone to be used for date output.'),
    '#options' => [
      '' => $this->t('- Default site/user timezone -'),
    ] + system_time_zones(FALSE, TRUE),
    '#default_value' => $this->options['timezone'],
  ];
  foreach (array_merge([
    'custom',
  ], array_keys($date_formats)) as $timezone_date_formats) {
    $form['timezone']['#states']['visible'][] = [
      ':input[name="options[date_format]"]' => [
        'value' => $timezone_date_formats,
      ],
    ];
  }
  parent::buildOptionsForm($form, $form_state);
}

In your case, the array returned from defineOptions() doesn't have the expected values (default or contains) and this is causing the issue you noticed.

1

$this->options and #options of the select element are two different things.

See the separator field of NumericField::buildOptionsForm:

$form['separator'] = [
  '#type' => 'select',
  '#title' => $this->t('Thousands marker'),
  '#options' => [
    '' => $this->t('- None -'),
    ',' => $this->t('Comma'),
    ' ' => $this->t('Space'),
    '.' => $this->t('Decimal'),
    '\'' => $this->t('Apostrophe'),
  ],
  '#default_value' => $this->options['separator'],
  '#description' => $this->t('What single character to use as the thousands separator.'),
  '#size' => 2,
];

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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