Create Smart Link custom field

Smart Link needs to hold the URL, and have additional values for the title.

Generate Field W/ Drush

Use drush to generate a custom field in the Smart Link module. This will create the field storage, widget, and formatter plugins.

andrew@InfoBox:~/Sites/mantra/web/sites/classes$ drush gen field


 Welcome to field generator!
–––––––––––––––––––––––––––––

 Module machine name:
 ➤ smart_link

 Field label [Example]:
 ➤ Smart link

 Field ID [smart_link_smart_link]:
 ➤ smart_link

 How many sub-fields would you like to create? [3]:
 ➤ 1
–––––––––––––––––––––––––––––––––––––––––––––––––––

 Label for sub-field #1 [Value 1]:
 ➤ URL

 Machine name for sub-field #1 [url]:
 ➤ 

 Type of sub-field #1 [Text]:
  [1 ] Boolean
  [2 ] Text
  [3 ] Text (long)
  [4 ] Integer
  [5 ] Float
  [6 ] Numeric
  [7 ] Email
  [8 ] Telephone
  [9 ] Url
  [10] Date
  ➤➤➤ 9

 Limit allowed values for sub-field #1? [No]:
 ➤ y

 Make sub-field #1 required? [No]:
 ➤ y
–––––––––––––––––––––––––––––––––––––––––––––––––––

 Would you like to create field storage settings form? [No]:
 ➤ y

 Would you like to create field instance settings form? [No]:
 ➤ y

 Would you like to create field widget settings form? [No]:
 ➤ y

 Would you like to create field formatter settings form? [No]:
 ➤ y

 Would you like to create table formatter? [No]:
 ➤ y

 Would you like to create key-value formatter? [No]:
 ➤ y

 The following directories and files have been created or updated:
–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
 • sites/classes/modules/custom/smart_link/config/schema/smart_link.schema.yml
 • sites/classes/modules/custom/smart_link/css/smart-link-widget.css
 • sites/classes/modules/custom/smart_link/smart_link.libraries.yml
 • sites/classes/modules/custom/smart_link/src/Plugin/Field/FieldFormatter/SmartLinkDefaultFormatter.php
 • sites/classes/modules/custom/smart_link/src/Plugin/Field/FieldFormatter/SmartLinkKeyValueFormatter.php
 • sites/classes/modules/custom/smart_link/src/Plugin/Field/FieldFormatter/SmartLinkTableFormatter.php
 • sites/classes/modules/custom/smart_link/src/Plugin/Field/FieldType/SmartLinkItem.php
 • sites/classes/modules/custom/smart_link/src/Plugin/Field/FieldWidget/SmartLinkWidget.php

Schema and Property Definitions

Let's look at the LinkItem class, which is a FieldType plugin.

These two functions control the field properties and database storage.

LinkItem.php
  /**
   * {@inheritdoc}
   */
  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
    $properties['uri'] = DataDefinition::create('uri')
      ->setLabel(t('URI'));

    $properties['title'] = DataDefinition::create('string')
      ->setLabel(t('Link text'));

    $properties['options'] = MapDataDefinition::create()
      ->setLabel(t('Options'));

    return $properties;
  }

  /**
   * {@inheritdoc}
   */
  public static function schema(FieldStorageDefinitionInterface $field_definition) {
    return [
      'columns' => [
        'uri' => [
          'description' => 'The URI of the link.',
          'type' => 'varchar',
          'length' => 2048,
        ],
        'title' => [
          'description' => 'The link text.',
          'type' => 'varchar',
          'length' => 255,
        ],
        'options' => [
          'description' => 'Serialized array of options for the link.',
          'type' => 'blob',
          'size' => 'big',
          'serialize' => TRUE,
        ],
      ],
      'indexes' => [
        'uri' => [['uri', 30]],
      ],
    ];
  }

Let's modify this to store the uri, title, domain, and h1 values we'll fetch from the link.

SmartLinkItem.php
  /**
   * {@inheritdoc}
   */
  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
    $properties['uri'] = DataDefinition::create('uri')
      ->setLabel(t('URI'));

    $properties['title'] = DataDefinition::create('string')
      ->setLabel(t('Link title'));

    $properties['domain'] = DataDefinition::create('string')
      ->setLabel(t('Link domain'));

    $properties['h1'] = DataDefinition::create('string')
      ->setLabel(t('First h1'));

    return $properties;
  }

  /**
   * {@inheritdoc}
   */
  public static function schema(FieldStorageDefinitionInterface $field_definition) {
    return [
      'columns' => [
        'uri' => [
          'description' => 'The URI of the link.',
          'type' => 'varchar',
          'length' => 2048,
        ],
        'title' => [
          'description' => 'The link title.',
          'type' => 'varchar',
          'length' => 255,
        ],
        'domain' => [
          'description' => 'The link domain.',
          'type' => 'varchar',
          'length' => 255,
        ],
        'h1' => [
          'description' => 'The first h1.',
          'type' => 'varchar',
          'length' => 255,
        ],
      ],
      'indexes' => [
        'uri' => [['uri', 30]],
      ],
    ];
  }

Widget Form Element

We need to define the field form elements in a FieldWidget plugin.

SmartLinkWidget.php
  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {

    $element['uri'] = [
      '#type' => 'url',
      '#title' => $this->t('URL'),
      '#default_value' => isset($items[$delta]->uri) ? $items[$delta]->uri : NULL,
      '#maxlength' => 2048,
      '#required' => $element['#required'],
    ];
    $element['title'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Link title'),
      '#default_value' => isset($items[$delta]->title) ? $items[$delta]->title : NULL,
    ];
    $element['domain'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Link domain'),
      '#default_value' => isset($items[$delta]->domain) ? $items[$delta]->domain : NULL,
    ];
    $element['h1'] = [
      '#type' => 'textfield',
      '#title' => $this->t('First h1'),
      '#default_value' => isset($items[$delta]->h1) ? $items[$delta]->h1 : NULL,
    ];

    return $element;
  }

Now there are some form fields we can see.

Smart Link form fields

Field Formatter

The formatter just puts the values into a render array.

SmartLinkDefaultFormatter.php
  public function viewElements(FieldItemListInterface $items, $langcode) {
    $element = [];

    foreach ($items as $delta => $item) {
      if ($item->domain) {
        $element[$delta]['url'] = [
          '#type' => 'item',
          '#title' => $this->t('URL'),
          '#markup' => $item->url
        ];
      }

      if ($item->domain) {
        $element[$delta]['domain'] = [
          '#type' => 'item',
          '#title' => $this->t('Domain'),
          '#markup' => $item->domain
        ];
      }

      if ($item->path) {
        $element[$delta]['path'] = [
          '#type' => 'item',
          '#title' => $this->t('Path'),
          '#markup' => $item->path
        ];
      }

      if ($item->title) {
        $element[$delta]['title'] = [
          '#type' => 'item',
          '#title' => $this->t('Title'),
          '#markup' => $item->title
        ];
      }

      if ($item->description) {
        $element[$delta]['description'] = [
          '#type' => 'item',
          '#title' => $this->t('Description'),
          '#markup' => $item->description
        ];
      }

      if ($item->h1) {
        $element[$delta]['h1'] = [
          '#type' => 'item',
          '#title' => $this->t('H1'),
          '#markup' => $item->h1
        ];
      }

    }

    return $element;
  }

 

Topics