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
  • 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 at 14:23
  • 1
    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 at 2:28

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.