Problem/Motivation
There is no easy way to add an attribute (class, title, rel, target) to the anchor tag of link field unless it is of the "Separate title and URL" format. No template is provided for the default format.
From field.html.twig
template:
<div{{ attributes.addClass(classes) }}>
{% if not label_hidden %}
<div{{ title_attributes.addClass(title_classes) }}>{{ label }}</div>
{% endif %}
<div{{ content_attributes.addClass('field-items') }}>
{% for item in items %}
<div{{ item.attributes.addClass('field-item') }}>{{ item.content }}</div>
{% endfor %}
</div>
</div>
item.content
contains the anchor tag of a link field.
From template_preprocess_field
:
$variables['items'] = array();
$delta = 0;
while (!empty($element[$delta])) {
$variables['items'][$delta]['content'] = $element[$delta];
// Modules (e.g., rdf.module) can add field item attributes (to
// $item->_attributes) within hook_entity_prepare_view(). Some field
// formatters move those attributes into some nested formatter-specific
// element in order have them rendered on the desired HTML element (e.g., on
// the <a> element of a field item being rendered as a link). Other field
// formatters leave them within $element['#items'][$delta]['_attributes'] to
// be rendered on the item wrappers provided by field.html.twig.
$variables['items'][$delta]['attributes'] = !empty($element['#items'][$delta]->_attributes) ? new Attribute($element['#items'][$delta]->_attributes) : clone($default_attributes);
$delta++;
}
$variables['items'][$delta]['attributes']
is rendered on the outer div <div{{ item.attributes.addClass('field-item') }}>
So the only possible way is to write a hook_entity_prepare_view
like rdf module does. Since themes can't add this hook, you have to write a custom module:
/**
* Implements hook_entity_prepare_view().
*/
function my_module_links_block_entity_prepare_view($entity_type_id, array $entities, array $displays, $view_mode) {
if ($entity_type_id == 'some_entity_type') {
foreach ($entities as $entity) {
if ($entity->bundle() == 'some_bundle') {
foreach ($displays[$entity->bundle()]->getComponents() as $name => $options) {
if ($name == 'some_link_field') {
foreach ($entity->get($name) as $item) {
$item->_attributes += array('class' => array('Yay-add-my-class'));
}
}
}
}
}
}
}
Proposed resolution
Move https://www.drupal.org/project/link_attributes to core
Remaining tasks
Add tests
Updating exisitng config in post update hook
Review
User interface changes
Link widget will allow to set attributes from ui.
API changes
None
Comment | File | Size | Author |
---|---|---|---|
#13 | 2477155-12.patch | 3.05 KB | jibran |
Comments
Comment #1
jibranFrom
LinkFormatter::buildUrl()
url options can be added using
$item->options
but there is no UI for that in field settings page.Comment #2
Mac_Weber CreditAttribution: Mac_Weber commented@jibran maybe we just need to add it to the UI settings? I've changed the issue summary accordingly.
Comment #3
rootworkIt would be really fantastic to have these in the UI (class, rel and target).
Is this still possible in the RC phase? If not I guess it should be postponed to 8.1.x, but maybe in the meantime we could document the custom module route -- my guess is a lot of themers are going to want to add classes to their links.
Comment #4
rootworkThinking about this more, is there a reason this couldn't be moved to a template like the other old field preprocess functions were? There's already a
link-formatter-link-separate.html.twig
template; if the functionality to render a link field could be moved to a template too, then themers could add attributes like class, title, rel, target etc. pretty easily.Comment #5
rootworkI read more from #1898426: link.module - Convert theme_ functions to Twig and I'm really confused why there's the
link-formatter-link-separate.html.twig
template but nothing for a (non-separated) link. If the theming functions for theme_link_formatter_link_separate were converted, why not for regular links? In fact link_theme only even mentions link_formatter_link_separate.Bizarre. I'm changing the title to try to get some feedback on my suggestion that we have a template for themed link fields, or at least some explanation of why that doesn't exist.
Comment #6
rootworkUpdated issue summary with clearer explanation; fixed a couple typos.
Comment #7
rootworkComment #8
mstrelan CreditAttribution: mstrelan commentedCan you give a specific example of how / where to add this? Can this be done in hook_preprocess_field()?
Comment #9
rootworkI take it that's a question for jibran.
Using the opportunity to move this to 8.1.
Comment #11
weseze CreditAttribution: weseze commentedThere seems to be some progress in contrib modules, but neither of them are working for me...
https://www.drupal.org/project/link_class
https://www.drupal.org/project/link_class_widget
The only working solution I found to this problem was to add a preprocess function in my theme!
I also tried in a field twig, but I could not figure out how to access the attributes array from there.
Is anything happening to include basic things like this in the Drupal core Link Formatter? Is there any reason this was not included?
Comment #12
rootwork@weseze Leah Wagner just wrote this up. You're right that currently the only way is to use a preprocess function, but her suggestion is a little more flexible:
In your
THEME.theme
file:And then in your theme's
field.twig.html
:This is extending the Stable theme's field template, but you could also extend the Classy theme instead. This is also applying it to all fields, but you could apply it just to link fields with a field-specific template. And this is programmatically adding classes based on the field name; if you want to just apply a specific class, you'd prepend (or replace) the
bundle...
line with the quoted class, i.e.'MYCLASS'
.That said, the original suggestion in this issue -- to make adding all attributes (including not just classes but things like title and rel) possible with a core link-field Twig template -- would be more flexible (and more understandable) still. So that's what I'm pulling for.
Comment #13
jibranLet's move https://www.drupal.org/project/link_attributes to core instead.
Comment #17
Jehu CreditAttribution: Jehu commentedwhat about title attribute?