0

When using a link field without a link text and just with the URL, Drupal 8/9 outputs the relative path as the link text for internal links. How can I change that to either output the absolute URL or (even better) use the title from the entity in the link as the link text?

I am using the "Separate link text and URL" formatter provided by Drupal core.

4
  • Does this answer your question? How to get the valid URL of a Link field from within a Twig template?
    – leymannx
    Feb 12, 2021 at 13:40
  • Output where? For what? Did you consider writing your own simple custom field formatter?
    – leymannx
    Feb 12, 2021 at 13:46
  • Thanks for your reply! I want to output a link field on a node, but ideally want to use the entity label as the link text, if no link text was provided by the editor. To achieve that from a field formatter, I would have to call the entity object of the linked entity from the field formatter. Is this possible or would I need a preprocess function? I must admit I am really a bit lost.
    – Extect
    Feb 12, 2021 at 14:03
  • I think it's possible, yes. From within a custom field formatter. You should get the parent entity and with a bit of magic should get the linked entity as well. But first of all you need to start to do something: Write a custom field formatter yourself and see how far you get.
    – leymannx
    Feb 12, 2021 at 14:22

2 Answers 2

1

Inspired by Link field title from entity/route, I created a preprocess function.

/**
 * Prepares variables for link fields.
 */
function mytheme_preprocess_field__node__field_links(&$variables) {
  /* If it's an internal link and there was no link title provided by the editor, 
then use the entity label as the link text.*/
  $i = 0;
  foreach ($variables['element']['#items'] as &$item) {
    if($item->getUrl()->isRouted()) {
      $parameters = $item->getUrl()->getRouteParameters();
      if (!empty($parameters)) {
        foreach ($parameters as $entity_type => $id) {
          if ($entity = Drupal::entityTypeManager()
            ->getStorage($entity_type)
            ->load($id)) {
            $variables['items'][$i]['content']['#url_title'] = Link::fromTextAndUrl($entity->label(), $entity->toURL())
              ->toString();
            break;
          }
        }
      }
    }
    $i++;
  }
}
4
  • Please only use answers to answer the question, not to post follow up questions. Thanks!
    – Clive
    Feb 12, 2021 at 14:46
  • I was just asking for validation of my answer. No follow-up answer. But thanks for editing it.
    – Extect
    Feb 12, 2021 at 15:23
  • An answer isn't an appropriate place to ask for a code review - please only use answers for answering the question. Thanks!
    – Clive
    Feb 12, 2021 at 15:27
  • To clarify - this is a Q+A site, we just want questions and their answers, anything else is considered noise - rest assured people will see your answer, and will point out mistakes or bad practice if they see them, it's implied by how the site works
    – Clive
    Feb 12, 2021 at 15:29
0

Alternatively to the code answer already posted, which is probably preferable because of better performance you could use Views to change the output of the Link Field.

  1. Hide the Link Field completely (drag to the Disabled area).

  2. Create Views with Block Display listing Content where you have the Link Field, set it to output Fields.

  3. Add the Title and the Link fields.

  4. Make sure the Title Field is set to Exclude from display and DON'T output as link to content!

    This way you will get the Title text to later act as link text.

  5. Change the Link Field configuration under Rewrite results: in Override the output of this field with custom text Text area put the token for the node Title, usually something like {{ title }}. (You can lookup available tokens further down the Field settings page under Replacement patterns)

  6. more under Rewrite results: Output this field as a custom link enter something like {{ field_link_uri }} into the Link path field and check the Use absolute path option.

    At this point you have a list of Links from all nodes.

  7. To make only the relevant Link appear in the Block add the Contextual filter for Content ID and provide default ID from URL (standard config you can find in other questions).

    This filters the results to the Link from only the node you're currently viewing. Enter the node ID into Views Preview field to test the Contextual is working correctly, at least in Views context.

  8. Now that the Link in Views is constructed place the Block into a theme Region, make it Visible only on your Content pages, and set the Contextual ID from URL option.

    You should now have the modified Link show up on node pages.

1
  • Ah! Nice alternative. I didn't even think about views to achieve that. Thanks for the hint! That's the power of Drupal: There are loads of different ways to solve things.
    – Extect
    Feb 13, 2021 at 6:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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