Hello,

I am trying to add in a Color Field to display the Widget Boxes and while looking through the code, I just cannot get it to display. Here is my code that I have that I'm trying to add the field for:

$form['bg_colors'] = [
              #type' => 'color_field_type',
              #title' => $this->t('Background Colors'),
              #default_value' => $this->configuration['bg_colors'],
              #description' => $this->t('Choose a background color for the whole layout.'),
            ];

But this doesn't render or show anything. If I change the '#type' variable to 'color', I get an HTML5 Color select box, but that will not work for me, as I need to limit the selection of colors to some very specific colors.

How can I implement the Color Field programmatically?

Comments

ZeiferPlays created an issue. See original summary.

kittiradovics’s picture

You will need a custom form element to be able to use it in a form. I created this one for my custom project, but it's not a perfect solution because it has redundant code from ColorFieldWidgetBox.php. It would be great to have form elements for each widget type in the module.

<?php

namespace Drupal\example\Element;

use Drupal\Component\Utility\Html;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element\FormElement;

/**
 * Provide a color box form element.
 *
 * Usage example:
 * @code
 * $form['color'] = [
 *   '#type' => 'color_field_element_box',
 *   '#title' => t('Color'),
 *   '#color_options' => [rgb(255,255,255), rgb(0,0,0)],
 *   '#required' => TRUE,
 *   '#default_value' => [
 *     'color' => rgb(255,255,255),
 *     'opacity' => 0.5,
 *   ],
 * ];
 * @endcode
 *
 * @FormElement("color_field_element_box")
 */
class ColorFieldElementBox extends FormElement {

  /**
   * {@inheritdoc}
   */
  public function getInfo(): array {
    $class = get_class($this);
    return [
      '#input' => TRUE,
      '#process' => [
        [$class, 'processColorFieldElementBox'],
      ],
    ];
  }

  /**
   * Create form element structure for color boxes provided by
   * color_field module.
   *
   * @param array $element
   *   The form element to process.
   * @param FormStateInterface $form_state
   *   The current state of the form.
   * @param array $form
   *   The complete form structure.
   *
   * @return array
   *   The form element.
   */
  public static function processColorFieldElementBox(array &$element, FormStateInterface $form_state, array &$form): array {
    $element['#uid'] = Html::getUniqueId($element['#name']);

    // Create fieldset of color and opacity.
    $element['settings'] = [
      '#type' => 'fieldset',
      '#title' => $element['#title'],
    ];
    $element['settings']['color'] = [
      '#type' => 'textfield',
      '#required' => $element['#required'],
      '#default_value' => $element['#default_value']['color'],
      '#suffix' => "<div class='color-field-widget-box-form' id='" . $element['#uid'] . "'></div>",
    ];
    if (isset($element['#default_value']['opacity'])) {
      $element['settings']['opacity'] = [
        '#title' => t('Opacity'),
        '#type' => 'number',
        '#min' => 0,
        '#max' => 1,
        '#step' => 0.01,
        '#required' => $element['#required'],
        '#default_value' => $element['#default_value']['opacity'],
        '#placeholder' => 1.0,
      ];
    }

    // Set Drupal settings.
    $settings[$element['#uid']] = [
      'required' => $element['#required'],
    ];

    // Add allowed colors for color boxes.
    foreach ($element['#color_options'] as $color) {
      $settings[$element['#uid']]['palette'][] = $color;
    }

    // Attach color_field module's library.
    $element['#attached']['library'][] = 'color_field/color-field-widget-box';
    $element['#attached']['drupalSettings']['color_field']['color_field_widget_box']['settings'] = $settings;

    return $element;
  }

}
cozydrupalnerd’s picture

Thank you for this! I'll give this a try and let you know if I have any other questions. :D

TheWinkingSkeever’s picture

I too am interested in this, but for spectrum widget. Have you got it working in the layout builder?

kittiradovics’s picture

No, unfortunately I don't have form elements for all widgets. You can use the code in formElement() methods of ColorFieldWidgetBase and ColorFieldWidgetSpectrum classes for creating your custom form element.

aliyakhan’s picture

Since color_field option is not available, try creating a select list of list colors. Adding example code:

$form['background_color'] = [
  '#type' => 'select',
  '#title' => $this->t('Background Color'),
  '#options' => [
    'black' => $this->t('Black'),
    'white' => $this->t('White'),
    'grey' => $this->t('Grey'),
  ],
  '#default_value' => $this->configuration['background_color'] ?? "black",
];
netprogfr’s picture

I know that this publication is quite old, but I think it is useful to know that there is a simple alternative solution to have a field with a color palette : Color.php (Drupal API)

le72’s picture

Thanks for the direction @kittiradovics. Here is my implementation of the spectrum widget.
If the patch is needed I can provide it. But it's may be better to develop a submodule with 3-4 new form elements.

use Drupal\Component\Utility\Html;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element\FormElement;

/**
 * Provide a color box form element.
 *
 * Usage example:
 * @code
 * $form['color'] = [
 *   '#type' => 'color_field_spectrum',
 *   '#title' => t('Color'),
 *   '#show_input => FALSE
 *   '#show_palette' => FALSE,
 *   '#palette' => [rgb(255,255,255), rgb(0,0,0)],
 *   '#show_palette_only' => FALSE,
 *   '#show_buttons' => FALSE,
 *   '#allow_empty' => FALSE,
 *   '#show_alpha' => TRUE,
 *   '#default_value' => [
 *     'color' => rgb(255,255,255),
 *     'opacity' => 0.5,
 *   ],
 * ];
 * @endcode
 *
 * @FormElement("color_field_spectrum")
 */
class ColorFieldSpectrum extends FormElement {

  public static function defaultSettings() {
    return [
        'show_input' => FALSE,
        'show_palette' => FALSE,
        'palette' => '',
        'show_palette_only' => FALSE,
        'show_buttons' => FALSE,
        'allow_empty' => FALSE,
        'show_alpha' => FALSE,
      ];
  }

  /**
   * {@inheritdoc}
   */
  public function getInfo(): array {
    $class = get_class($this);
    return [
      '#input' => TRUE,
      '#process' => [
        [$class, 'processColorFieldSpectrum'],
      ],
    ];
  }

  /**
   * Create form element structure for color boxes provided by
   * color_field module.
   *
   * @param array $element
   *   The form element to process.
   * @param FormStateInterface $form_state
   *   The current state of the form.
   * @param array $form
   *   The complete form structure.
   *
   * @return array
   *   The form element.
   */
  public static function processColorFieldSpectrum(array &$element, FormStateInterface $form_state, array &$form): array {

    $element['#uid'] = Html::getUniqueId($element['#name']);
    $element['#attached']['library'][] = 'color_field/color-field-widget-spectrum';

    // Set Drupal settings.
    $settings = self::defaultSettings();
    $settings['required'] = $element['#required'];
    if (isset($element['#show_input'])) {
      $settings['show_input'] = $element['#show_input'];
    }
    if (isset($element['#show_palette'])) {
      $settings['show_palette'] = $element['#show_palette'];
    }
    if (isset($element['#palette'])) {
      $settings['palette'] = $element['#palette'];
    }
    if (isset($element['#show_palette_only'])) {
      $settings['show_palette_only'] = $element['#show_palette_only'];
    }
    if (isset($element['#show_buttons'])) {
      $settings['show_buttons'] = $element['#show_buttons'];
    }
    if (isset($element['#allow_empty'])) {
      $settings['allow_empty'] = $element['#allow_empty'];
    }

    if (isset($element['#show_alpha']) && isset($element['#default_value']['opacity'])) {
      $settings['show_alpha'] = $element['#show_alpha'];
      $element['settings']['opacity'] = [
        '#type' => 'textfield',
        '#default_value' => $element['#default_value']['opacity'],
      ];
    }

    // Create fieldset of color and opacity.
    $element['settings'] = [
      '#type' => 'fieldset',
      '#title' => $element['#title'],
    ];
    $element['settings']['#attributes']['id'] = $element['#uid'];
    $element['settings']['#attributes']['class'][] = 'js-color-field-widget-spectrum';

    $element['settings']['color'] = [
      '#type' => 'textfield',
      '#default_value' => $element['#default_value']['color'],
    ];
    $element['settings']['color']['#attributes']['class'][] = 'js-color-field-widget-spectrum__color';


    $element['settings']['opacity']['#attributes']['class'][] = 'js-color-field-widget-spectrum__opacity';

    $element['settings']['#attached']['drupalSettings']['color_field']['color_field_widget_spectrum'][$element['#uid']] = $settings;

    return $element;

  }

}
nickdickinsonwilde’s picture

Status: Active » Closed (duplicate)

Sounds like working with layout builder (and working for me) with #3183101: jQuery spectrum widget text input does not work with modals

schoenef’s picture

#8 works fantastic! Thx @le72.

I feel this is kind of a missing feature of the moule.