I'm using a pattern 'card', which displays cards in a block on the home page. The pattern is based on a ds View Mode of the Content Type. Each card should be contained in an anchor tag so the whole card can be clicked. Destinations of the links should be the default View Mode of each node. Each node's title is used as a url alias, so node/2 has an alias of /honey. The title field is available in my pattern yml.

I'm struggling to write the anchor tag in my twig template.
I first tried the intuitive solution
<a href="/{{title}}">
which produces strange results.

I started googling and realised I've stumbled into a collision of conventions. I've been reading about twig url/path, drupal routes and ui_patterns. It seems like all 3 are coming to the party.

For example
<a href="{{ url('<front>') }}">
works, but putting the variable {{title}} in there breaks it, whatever I try.

I'm a site builder rather than a developer. Can anyone show me how to code the href in my pattern-card.html.twig?

Comments

nigelwhite created an issue. See original summary.

nigelwhite’s picture

Issue summary: View changes
nigelwhite’s picture

Issue summary: View changes
nigelwhite’s picture

Issue summary: View changes
pdureau’s picture

Assigned: Unassigned » ademarco

hello @nigelwhite

It is great to have you as an user. I understand you are a site builder rather than a developer, so sorry if my answer is too technical.

Direct answer

Each node's title is used as a url alias, so node/2 has an alias of /honey.

I will not advice doing that, recreating the path from other fields. Drupal already know the path and can retrieve and inject it for you, i will propose something later in the message.

Putting the variable {{title}} in there breaks it, whatever I try.

Usually, using pattern fields to feed HTML elements attributes, like anchor href attribute, is OK. You just need to be careful you are sending pure textual data and not a renderable array or object.

Where are you retrieving your node title from? A field formatter? if so, use a field formatter like the "Plain text" (string) formatter provided by Core. If I remember right, this formatter will inject only the text value of the node, and it will work as expected.

Better proposal

There are 2 things wrong about my direct answer:

  • as previously say, you are not really injecting the node link, but are trying to rebuilding it in the Twig template
  • when using a visual page builder, like the layout builder module, you also need to be careful because the preview markup will also be injected and may break stuff.

If it is your case, and if you have the ability to change the card CSS, i will inject the link element itself instead of just the URL, and start something like that (not tested proposal):

<div {{ attributes.addClass('card') }}>
  ...
  <div class="card__link">{{ link }}</div>
</div>

:not(.layout-builder__section)  .card__link {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
}
:not(.layout-builder__section) .card__link a {
      position: absolute;
      left: 0;
      top: 0;
      width: 100%;
      height: 100%;
    }
  }

And then, use the same "Plain text" (string) formatter and check the " Link to the Content" setting. It will produce a HTML link element markup, which will be managed correctly.

pdureau’s picture

Assigned: ademarco » Unassigned
pdureau’s picture

Status: Active » Needs review
pdureau’s picture

nigelwhite’s picture

StatusFileSize
new46.09 KB
new41.84 KB

Thank you for your answer and explanation. Here are the results...

Here is my pattern twig

<a href="{{ title }}" class="ink-card mx-auto">
	<div class="ink-card-image position-relative">{{image}}
		<div class="ink-card-title position-absolute bottom-0 start-0 fs-3">{{title}}</div>
		<div class="ink-card-badge position-absolute top-0 start-100">{{badge}}</div>
	</div>
</a>

Your first suggestion -

use a field formatter like the "Plain text" (string) formatter provided by Core. If I remember right, this formatter will inject only the text value of the node, and it will work as expected

I am using DS. The only field formatter provided by core on the title field is "Default". It comes with a h2 wrapper, but I have removed this. The result is
honey1

Result = The link is placed on only the title. It should be on the whole card. The 'link to the content' setting in DS makes no difference here. The title 'Honey' above the card should not even be there. Both links have the correct destination '/honey'

Your second suggestion _

inject the link element itself instead of just the URL

I changed my twig to

<a href="{{ link }}" class="ink-card mx-auto">
	<div class="ink-card-image position-relative">{{image}}
		<div class="ink-card-title position-absolute bottom-0 start-0 fs-3">{{title}}</div>
		<div class="ink-card-badge position-absolute top-0 start-100">{{badge}}</div>
	</div>
</a>

So I have put {{link}} instead of {{title}}

The CSS is

:not(layout-builder__section) .ink-card {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
}
:not(layout-builder__section) .ink-card a {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
}

[I don't know what this CSS does]
The 'link to the content' setting in DS is on.

Result
honey2
There is a link on the title, which points to the correct content (ie /honey). There is a link on the whole card, which points to the homepage in every case.

Do you know anything else I could try?

pdureau’s picture

I don't know what this CSS does

This CSS was an untested idea (I am not a front dev) and related to Layout Builder. You are using Display Suite instead, which is using the admin theme, so forget everything I said about using a visual page builder.

The only field formatter provided by core on the title field is "Default".

If this formatter is producing raw text value instead of markup, it is OK.

The link is placed on only the title. It should be on the whole card.

Maybe it is a pure "CSS in the browser" issue? Do you have an HTML link (injected in image, title or badge) into an HTML link (the wrapper)? I tcan turn the browsers crazy.

duaelfr’s picture

To answer your original question, there are multiple ways to solve your issue:

  • Putting your link drupal field in your url pattern field using a Formatter that only renders the URL. This need to choose the "Only content" option in the "Field template" setting to avoid having the markup around your content. This doesn't need anything else than UI Patterns but the downside of this method is that ALL your fields will be rendered without wrappers and labels.

  • Creating an extra field in the code that only returns the value without any wrapper and put it in the url pattern field. It needs the patch from #3311088: Add extra field support to be applied on UI Patterns and to know how to code a bit to create the extra field.
  • Use the UI Patterns Settings module to define the url not as a pattern field but as a pattern setting and to allow using tokens to define this settings. This needs an additional module and some understanding of tokens but it's the easiest way to get it done.

duaelfr’s picture

Quick update: I just discovered the No Markup module that could be an addition to the first option I described above. Instead of marking all fields as not having markup, you can use this module to do it field by field.

duaelfr’s picture

Status: Needs review » Fixed

The questions has been answered. Do not hesitate to reopen if needed.

grimreaper’s picture

Updating issue credits.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

nigelwhite’s picture

Thank you for these ideas. [Coming back to this after a while, so sorry for the delay]

Two of your ideas worked for me. To summarize for any other site builders who are puzzled -

  • fields you want to format with your pattern must be plain text or link. Even then Drupal will add a load of html markup around your field, which will throw your pattern's twig
  • either remove markup from all fields in your display as per #11. At the bottom of /admin/structure/types/manage/your-content-type/display you will find a Pattern Settings tab. Set Field Templates to 'Only content'.
  • or remove markup from fields individually by installing nomarkup module as per #12. Each field's settings cog has a 'Remove field markup' option

For links -

  • in yml your link field is type 'uri'
  • in pattern preview this worked for me: preview: "<a href='https://example.com/'>Link to source</a>"
  • in twig a simple {{ your-field }} is all you need
  • when adding content in the node add form the url and the link text are what you'd expect

Thank you for a great module