1

I need a field type with 3 select in it. The field type is created and works like a charm but I'd like one of these select may have multiple values. What must I change? I add '#multiple' => TRUE, in the widget. But I can't save my values. I should probably change the type of field in the FieldType but how? Thanks in advance.

/**
 * Provides a field type of resource.
 *
 * @FieldType(
 *   id = "resource",
 *   label = @Translation("Resource"),
 *   default_formatter = "resource_formatter",
 *   default_widget = "resource_widget",
 * )
 */
class ResourceItem extends FieldItemBase {

  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
    $properties = [];
    $properties['topic'] = DataDefinition::create('string');
    $properties['material'] = DataDefinition::create('string');
    $properties['add_infos'] = DataDefinition::create('string');
    $properties['columns_display'] = DataDefinition::create('string');

    return $properties;
  }

  public static function schema(FieldStorageDefinitionInterface $field_definition) {
    return [
      'columns' => [
        'topic' => [
          'type' => 'varchar',
          'length' => '255',
          'not null' => FALSE,
        ],
        'material' => [
          'type' => 'varchar',
          'length' => '255',
          'not null' => FALSE,
        ],
        'add_infos' => [
          'type' => 'varchar',
          'length' => '255',
          'not null' => FALSE,
        ],
        'columns_display' => [
          'type' => 'varchar',
          'length' => '255',
          'not null' => FALSE,
        ],
      ],
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function isEmpty() {
    $value1 = $this->get('topic')->getValue();
    $value2 = $this->get('material')->getValue();
    $value3 = $this->get('add_infos')->getValue();
    $value4 = $this->get('columns_display')->getValue();
    return empty($value1) && empty($value2) && empty($value3) && empty($value4);
  }

}
/**
 * Plugin implementation of the 'topic_widget' widget.
 *
 * @FieldWidget(
 *   id = "resource_widget",
 *   label = @Translation("Resource default"),
 *   field_types = {
 *     "resource"
 *   }
 * )
 */
class ResourceDefaultWidget extends WidgetBase {

  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
    $config = \Drupal::config('resources.config');


    $json_topics = file_get_contents($config->get('global_config.url_api') . '/topics');
    $topics = Json::decode($json_topics);
    $options_topics[0] = '--- Choose topic ---';
    foreach ($topics as $key => $topic) {
      $options_topics[$topic['name']] = ucfirst($topic['name']);
    }
    $element['topic'] = [
      '#type' => 'select',
      '#title' => t('Topic'),
      '#description' => t('List of topics from osteoporosis-foundation'),
      '#options' => $options_topics,
    ];


    $json_materials = file_get_contents($config->get('global_config.url_api') . '/materials');
    $materials = Json::decode($json_materials);
    $options_mat[0] = '--- Choose material ---';
    foreach ($materials as $key => $material) {
      $options_mat[$material['name']] = ucfirst($material['name']);
    }
    $element['material'] = [
      '#type' => 'select',
      '#title' => t('Material'),
      '#description' => t('List of materials from osteoporosis-foundation'),
      '#options' => $options_mat,
    ];


    $json_add_infos = file_get_contents($config->get('global_config.url_api') . '/additional-information');
    $add_infos = Json::decode($json_add_infos);
    $options_add_infos[0] = '--- Choose additional information ---';
    foreach ($add_infos as $key => $info) {
      $options_add_infos[$info['name']] = ucfirst($info['name']);
    }
    $element['add_infos'] = [
      '#type' => 'select',
      '#title' => t('Additional Information'),
      '#multiple' => TRUE,
      '#description' => t('List of additional information from osteoporosis-foundation'),
      '#options' => $options_add_infos,
    ];


    $element['columns_display'] = [
      '#type' => 'select',
      '#title' => t('Number of column to display'),
      '#options' => [
        'null'     => '--- Choose column(s) to display ---',
        'col-md-3' => '1 column',
        'col-md-6' => '2 columns',
        'col-md-9' => '3 columns',
        'col-md-12' => '4 columns',
      ],
    ];


    //setting default value to all fields from above
    $childs = Element::children($element);
    foreach ($childs as $child) {
      $element[$child]['#default_value'] = isset($items[$delta]->{$child}) ? $items[$delta]->{$child} : NULL;
    }

    return $element;
  }

}

/**
 * Plugin implementation of the 'resource_formatter' formatter.
 *
 * @FieldFormatter(
 *   id = "resource_formatter",
 *   label = @Translation("Resource default"),
 *   field_types = {
 *     "resource"
 *   }
 * )
 */
class ResourceDefaultFormatter extends FormatterBase{

  public function viewElements(FieldItemListInterface $items, $langcode) {
    $config = \Drupal::config('resources.config');

    $element = [];

    foreach ($items as $delta => $item) {
      $column_display = $item->columns_display;

      $topics = 'topics=' . str_replace(' ', '+', $item->topic);
      $materials = '&materials=' . str_replace(' ', '+', $item->material);
      $additional_info = '&additional_info=' . str_replace(' ', '+', $item->add_infos);

      $json_all  = file_get_contents($config->get('global_config.url_api').'/all' . '?' . $topics . $materials . $additional_info);

      $all_content       = Json::decode($json_all);

      foreach ($all_content['rows'] as $key => $content){
        $type_explode = explode('-', $content['type']);
        $type = strtolower(str_replace(' ', '_', trim(end($type_explode))));

        switch($type){
          case ('remote_videos'):
            $element[] = [
              '#theme' => 'video',
              '#resource' => $content,
              '#column_display' => $column_display
            ];
            break;
          default:
            $element[] = [
              '#theme' => 'file',
              '#resource' => $content,
              '#column_display' => $column_display
            ];
        }
      }
    }

    return $element;
  }

}
4

1 Answer 1

1

I update my code following the 4k4's comment and now it works. Thanks for your help

/**
 * Plugin implementation of the 'topic_widget' widget.
 *
 * @FieldWidget(
 *   id = "resource_widget",
 *   label = @Translation("Resource default"),
 *   field_types = {
 *     "resource"
 *   }
 * )
 */
class ResourceDefaultWidget extends WidgetBase {

  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
    $config = \Drupal::config('resources.config');


    $json_topics = file_get_contents($config->get('global_config.url_api') . '/topics');
    $topics = Json::decode($json_topics);
    $options_topics[0] = '--- Choose topic ---';
    foreach ($topics as $key => $topic) {
      $options_topics[$topic['name']] = ucfirst($topic['name']);
    }
    $element['topic'] = [
      '#type' => 'select',
      '#title' => t('Topic'),
      '#description' => t('List of topics from osteoporosis-foundation'),
      '#default_value' => isset($items[$delta]->topic) ? $items[$delta]->topic : NULL,
      '#options' => $options_topics,
    ];


    $json_materials = file_get_contents($config->get('global_config.url_api') . '/materials');
    $materials = Json::decode($json_materials);
    $options_mat[0] = '--- Choose material ---';
    foreach ($materials as $key => $material) {
      $options_mat[$material['name']] = ucfirst($material['name']);
    }
    $element['material'] = [
      '#type' => 'select',
      '#title' => t('Material'),
      '#description' => t('List of materials from osteoporosis-foundation'),
      '#default_value' => isset($items[$delta]->material) ? $items[$delta]->material : NULL,
      '#options' => $options_mat,
    ];


    $json_add_infos = file_get_contents($config->get('global_config.url_api') . '/additional-information');
    $add_infos = Json::decode($json_add_infos);
    $options_add_infos[0] = '--- Choose additional information ---';
    foreach ($add_infos as $key => $info) {
      $options_add_infos[$info['name']] = ucfirst($info['name']);
    }
    $element['add_infos'] = [
      '#type' => 'select',
      '#title' => t('Additional Information'),
      '#multiple' => TRUE,
      '#description' => t('List of additional information from osteoporosis-foundation'),
      '#default_value' => isset($items[$delta]->add_infos) ? unserialize($items[$delta]->add_infos) : NULL,
      '#options' => $options_add_infos,
    ];


    $element['columns_display'] = [
      '#type' => 'select',
      '#title' => t('Number of columns to display'),
      '#default_value' => isset($items[$delta]->columns_display) ? $items[$delta]->columns_display : NULL,
      '#options' => [
        'null'     => '--- Choose column(s) to display ---',
        'col-md-12' => '1 column',
        'col-md-9' => '2 columns',
        'col-md-6' => '3 columns',
        'col-md-3' => '4 columns',
      ],
    ];


    //setting default value to all fields from above
    /*$childs = Element::children($element);
    foreach ($childs as $child) {
      $element[$child]['#default_value'] = isset($items[$delta]->{$child}) ? $items[$delta]->{$child} : NULL;
    }*/

    return $element;
  }

  public function massageFormValues(array $values, array $form, FormStateInterface $form_state) {
    if($values[0]['add_infos'] != '0'){
      $values[0]['add_infos'] = serialize($values[0]['add_infos']);
    }

    return $values;
  }

}

1
  • Please post the code updates in the answer.
    – 4uk4
    Commented Nov 24, 2020 at 16:17

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.