1

I want to add a link field to my custom form.
Below is the code that I have been trying to use but no success. So can anyone let me know how to use core link field in a custom form in Drupal8?
The below code works for Drupal7 but not for Drupal8. I have also tried using #type => 'link' in the below code.

$form['cta'] = [
  '#type' => 'link_field',
  '#field_name' => 'link_field',
  '#field_parents' => array(),
  '#delta' => 0,  
];
return $form;
0

If you have a link field attached to any entity like a node bundle, or user or ... then you can use a code like this:

// Create an empty representative entity.
$node = \Drupal::service('entity_type.manager')
  ->getStorage('node')->create(['type' => 'article']);

// Get the EntityFormDisplay (i.e. the default Form Display) of this content
// type.
$entity_form_display = \Drupal::service('entity_type.manager')
  ->getStorage('entity_form_display')->load('node.article.default');

// Get the body field widget and add it to the form.
if ($widget = $entity_form_display->getRenderer('body')) { // Returns the widget class.
  $items = $node->get('body'); // Returns the FieldItemsList interface.
  $items->filterEmptyItems();
  $form['body'] = $widget->form($items, $form, $form_state); // Builds the widget form and attach it to your form.
  $form['body']['#access'] = $items->access('edit');
}
0

I think you have to create two seperate form fields to do this in Drupal 8.

You can use textfield for the title and url for the URL field, like this:

$form['cta_title'] = [
  '#type' => 'textfield',
  '#title' => t('CTA Title'),
];

$form['cta_url'] = [
  '#type' => 'url',
  '#title' => t('CTA Url'),
];

return $form;

Another solution is to pull the widget out from an entity display. There is a guide how to do that here, https://www.webomelette.com/how-render-entity-field-widgets-inside-custom-form-drupal-8.

Basically you load the entity display,

$entity = $this->entityTypeManager->getStorage('node')->create(['type' => 'article']);
$form_display = $this->entityTypeManager->getStorage('entity_form_display')->load('node.article.custom_form_display');

And then you pull out the widgets and add them to your form,

foreach ($form_display->getComponents() as $name => $component) {
  $widget = $form_display->getRenderer($name);
  if (!$widget) {
    continue;
  }

  $items = $entity->get($name);
  $items->filterEmptyItems();
  $form[$name] = $widget->form($items, $form, $form_state);
  $form[$name]['#access'] = $items->access('edit');
}
  • 2
    I am aware of this possibility. At last I will go with this only if I did not get to make that work.However I want to know if there is any way so that we can use the core link field widget in a custom form that gives us the same widget as we get when we create a link field in a content type created through admin UI. – sandeep tanwar Dec 9 '19 at 10:15
0

Thanks for the comments, both of you have actually redirected me in the right direction. Below are the actual steps that I took to achieve this:

  • Create a link field (field_url) in one of the content types using admin UI. and use the below code to use that field widget in your custom form or custom block.

    $form['#parents'] = [];
    // Create an empty representative entity.
    $node = \Drupal::service('entity_type.manager')->getStorage('node')->create([
      'type' => 'upcoming_webinar',
    ]
    );
    // Get the EntityFormDisplay (i.e. the default Form Display) of this content type.
    $entity_form_display = \Drupal::service('entity_type.manager')->getStorage('entity_form_display')
      ->load('node.upcoming_webinar.default');
    // Get the body field widget and add it to the form.
    // Returns the widget class.
    if ($widget = $entity_form_display->getRenderer('field_url')) {
      // Returns the FieldItemsList interface.
      $items = $node->get('field_url');
      $items->filterEmptyItems();
      // Builds the widget form and attach it to your form.
      $form['field_url'] = $widget->form($items, $form, $form_state);
      $form['field_url']['#access'] = $items->access('edit');
    }
    
  • 1
    Hmm, as far as I see this is pretty much the same answer as mine. – user72672 Dec 9 '19 at 15:09
0

Core's link field actually uses a '#type' => 'url' form element as base and if the field is configured to support internal links it switches to '#type' => 'entity_autocomplete'. See /core/modules/link/src/Plugin/Field/FieldWidget/LinkWidget.php L186-203

So if you just want to be able to select entities go for '#type' => 'entity_autocomplete'.

$form['cta'] = [
  '#type' => 'entity_autocomplete',
  '#target_type' => 'node',
];

And if you want to be able to type external URLs there as well you need to override the element validation yourself. Nonetheless you need to add your own simple '#type' => 'textfield' element to pick up a user entered title. Same as the link widget does it.

Your Answer

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

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