1

I'm trying to create a custom compound field in D8 that, among others, includes an entity_reference to a node and an entity_reference to a taxonomy term. I did follow the answer from this question. This works well for 1 entity_reference field combined with some additional fields. However, how can I get multiple entity_reference fields in one custom compound field? I used to solve this using paragraph fields but found this tedious to work with.

The current solution works as I do see an entity_reference field and some other fields (2 checkboxes and a date field). However, I don't see the second entity_reference (account_type) field and I'm not sure how to include it.

Here's the code, following the @oknate's answer and this lullabot tutorial from the linked question.

namespace Drupal\my_module\Plugin\Field\FieldType-->

/**
 * Field type "club_account_details".
 *
 * @see https://drupal.stackexchange.com/questions/230867/entity-reference-in-custom-field-type
 *
 * @FieldType(
 *   id = "club_account_details",
 *   label = @Translation("Club account details"),
 *   description = @Translation("Custom compound field club account details."),
 *   category = @Translation("Club Account Details"),
 *   default_widget = "club_account_details_default",
 *   default_formatter = "club_account_details_default",
 *   list_class = "\Drupal\Core\Field\EntityReferenceFieldItemList"
 * )
 */    
class ClubAccountDetails extends EntityReferenceItem {

      /**
       * {@inheritdoc}
       */
      public static function defaultStorageSettings() {
        return array(
            'target_type' => \Drupal::moduleHandler()->moduleExists('group') ? 'group' : 'node',
            'active_delete_request' => '',
            'was_merged' => '',
            'account_expiration' => '',
            'account_type' => '',
          ) + parent::defaultStorageSettings();
      }

      /**
       * {@inheritdoc}
       */
      public static function defaultFieldSettings() {
        return array(
            'handler' => 'default',
            'handler_settings' => array(),
          ) + parent::defaultFieldSettings();
      }

      /**
       * {@inheritdoc}
       */
      public static function schema(FieldStorageDefinitionInterface $field_definition) {
        $schema = parent::schema($field_definition);

        $schema['columns'] = array(
          'target_id' => $schema['columns']['target_id'],
          'active_delete_request' => array(
            'type' => 'int',
            'size' => 'tiny',
          ),
          'was_merged' => array(
            'type' => 'int',
            'size' => 'tiny',
          ),
          'account_expiration' => array(
            'type' => 'varchar',
            'mysql_type' => 'datetime',
          ),
          'account_type' => $schema['columns']['target_id']
        );
        return $schema;
      }

      /**
       * {@inheritdoc}
       */
      public static function mainPropertyName() {
        return 'target_id';
      }

      /**
       * {@inheritdoc}
       */
      public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
        $properties = parent::propertyDefinitions($field_definition);

        $properties['active_delete_request'] = DataDefinition::create('string')
          ->setLabel(t('Active deletion request'));
        $properties['was_merged'] = DataDefinition::create('boolean')
          ->setLabel(t('Was the group merged?'));
        $properties['account_expiration'] = DataDefinition::create('string')
          ->setLabel(t('Date of account expiration'))
          ->setSettings([
            'datetime_type' => 'date',
          ]);

        // This is my attempt to include another entity_reference field. The way it's done here does not even show a field in the admin form.
        $properties['account_type'] = DataDefinition::create('entity_reference')
          ->setLabel(t('The account type'))
          ->setSetting('target_type', 'taxonomy_term')
          ->setSetting('handler', 'default:taxonomy_term')
          ->setSetting('handler_settings',
            array(
              'target_bundles' => array(
                'group_account_type' => 'group_account_type'
              )
            )
          );
        return $properties;
      }

    }

namespace Drupal\my_module\Plugin\Field\FieldFormatter -->

/**
 * Field formatter "club_account_details_default".
 *
 * @FieldFormatter(
 *   id = "club_account_details_default",
 *   label = @Translation("Club account details default"),
 *   field_types = {
 *     "club_account_details",
 *   }
 * )
 */
class ClubAccountDetailsDefaultFormatter extends EntityReferenceLabelFormatter {

  /**
   * {@inheritdoc}
   */
  public function viewElements(FieldItemListInterface $items, $langcode) {
    $elements = parent::viewElements($items, $langcode);
    $values = $items->getValue();

    return $elements;
  }

}

and namespace Drupal\my_module\Plugin\Field\FieldWidget-->

/**
 * Field widget "club_account_details_default".
 *
 * @FieldWidget(
 *   id = "club_account_details_default",
 *   label = @Translation("Club account details default"),
 *   field_types = {
 *     "club_account_details",
 *   }
 * )
 */
class ClubAccountDetailsDefaultWidget extends EntityReferenceAutocompleteWidget {

  /**
   * {@inheritdoc}
   */
  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
    $widget = parent::formElement($items, $delta, $element, $form, $form_state);

    $widget['active_delete_request'] = array(
      '#title' => t('Active deletion request'),
      '#type' => 'checkbox',
      '#default_value' => isset($items[$delta]->active_delete_request) ? $items[$delta]->active_delete_request : 0,
    );
    $widget['was_merged'] = array(
      '#title' => t('Was the group merged?'),
      '#type' => 'checkbox',
      '#default_value' => isset($items[$delta]->was_merged) ? $items[$delta]->was_merged : 0,
    );
    $widget['account_expiration'] = array(
      '#type' => 'datetime',
      '#title' => 'Account expiration',
      '#default_value' => '',
      '#format' => 'Y/m/d',
      '#description' => t('z.B. 13/06/2016'),
    );
    $widget['account_type'] = array(
      '#title' => t('The account type?'),
      '#type' => 'entity_reference_autocomplete'
    );
    return $widget;
  }

}
  • Can you please post your code, thanks! – user72672 Dec 10 '19 at 11:16
  • Each property of the field is stored in one column of the database. The schema maps properties from the field object into columns of the database table. You can't map two properties (target_id, account type) into one schema column (target_id) – Hudri Dec 10 '19 at 21:50
  • well yes, I got that, as I said this is a first attempt and I know it's not working as coded, but I've no idea how to do it – theuni Dec 11 '19 at 5:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.