I want add link field (label + url internal/external) in custom form

This not work:

$form['test_ink'] = array(
  '#type' => 'link',
  '#title' => $this->t('Link title'),
  '#url' => '',

The link (Link) render element type is used to render an anchor element on a page, and not used to provide an input element in a form that is constrained for URLs.

As an example you may look at LinkWidget::formElement, which shows how that field widget creates form elements for a Link field. And the way it does this is to use the url (Url) form element, which will provide an input element that validates URLs. Make sure that the #url property is a valid (Url) object.

$form['test_ink'] = [
  '#type' => 'url',
  '#title' => $this->t('Link title'),
  // Example of a Url object from a route. See the documentation
  // for more methods that may help generate a Url object.
  '#url' => Url::fromRoute('entity.node.canonical', ['node' => 1]),


  1. Added @imclean's suggestion to the answer for readability
  • 3
    Note that for internal links the url type is not used, rather the entity_autocomplete.
    – Tim
    Feb 22 '17 at 9:23
  • 1
    Note that you can also use the linkit element if you have the linkit module (see drupal.org/project/linkit): $form['test_ink'] = [ '#type' => 'linkit', '#autocomplete_route_name' => 'linkit.autocomplete', '#autocomplete_route_parameters' => [ 'linkit_profile_id' => 'default', ], ]
    – mpp
    Jul 17 '19 at 14:23
  • 2
    Make sure the URL is a URL object or it simply won't work. For example: use Drupal\Core\Url; $element['test_link'] = [ '#type' => 'link', '#title' => t('Link title'), '#url' => Url::fromRoute('entity.node_type.collection'), ];
    – imclean
    Aug 23 '19 at 2:28

I liked @mpp's answer on how to create a linkit field if you have Linkit module enabled. His example was not code formatted, so this is just a repost using formatted code for better readability and to make it easier to copy paste this to use in your own projects. Create a linkit field with Drupal's form api:

$form['block_link'] = [
  '#type' => 'linkit',
  '#title' => $this->t('Select link target'),
  '#description' => $this->t('Start typing to see a list of results. Click to select.'),
  '#autocomplete_route_name' => 'linkit.autocomplete',
  '#autocomplete_route_parameters' => [
    'linkit_profile_id' => 'default',
  '#default_value' => isset($config['block_link']) ? $config['block_link'] : '',

Note that you can change 'default' to any linkit profile you might have in your project. Also note: my default value in this case comes from a block config form because I added this linkit field to a block's settings page. Remove #default_value if it is not applicable to your case or change it depending on where you get your value from.


I was facing this problem when I needed to add a link (url+label) to the theme settings form. I didn't use the url field cause it has a bug if the user wants to add an internal link.

This is how it looked on the CMS:

enter image description here

This is the code:

 * Implements hook_form_system_theme_settings_alter().
function francisco_form_system_theme_settings_alter(&$form, \Drupal\Core\Form\FormStateInterface &$form_state, $form_id = NULL) {
  // Work-around for a core bug affecting admin themes. See issue #943212.
  if (isset($form_id)) {

  $form['francisco_theme_option_sidebar'] = array(
    '#type' => 'details',
    '#title' => t('Sidebar'),
    '#description' => t('Lorem ipsum.'),
    '#open' => TRUE,

  $form['francisco_theme_option_sidebar']['francisco_theme_option_sidebar_footer_cta_title'] = array(
    '#type'          => 'textfield',
    '#title'         => t('Link Title'),
    '#default_value' => theme_get_setting('francisco_theme_option_sidebar_footer_cta_title'),
    '#description'   => t("Lorem ipsum."),
    '#maxlength' => 255

  $form['francisco_theme_option_sidebar']['francisco_theme_option_sidebar_footer_cta_url'] = array(
    '#type'          => 'textfield',
    '#title'         => t('URL'),
    '#default_value' => theme_get_setting('francisco_theme_option_sidebar_footer_cta_url'),
    '#description'   => t("Lorem ipsum."),
    '#maxlength' => 2048,


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.