cms
cms copied to clipboard
Link field type
Description
Adds a new “Link” field type, which replaces the former “URL” field type.
Link fields feature a simple UI for defining a link, of one of the allowed types the field was configured with:
- URL
- Asset
- Category
- Entry
- Phone
Textual link types automatically set valid values to hyperlinks on blur, or when the Esc key is pressed. Hyperlinks are automatically replaced with text inputs when the input container is clicked on, or the “Edit” disclosure menu option is chosen.
Templating/GraphQL
Regardless of the link type selected, field values will return the full, rendered URL.
# GraphQL query
query {
entry(id: 99) {
...on link_Entry {
link1
link2
link3
}
}
}
// Response
{
"data": {
"entry": {
"link1": "https://craftcms.com",
"link2": "https://console.craftcms.com",
"link3": "https://craft5.ddev.site/work"
}
}
}
The following properties are also available off of the value in Twig templates:
type– The link type’s ID (url,category,email,entry, ortel)label– A suggested label that could be used in anchor links (e.g. the URL sans-schema, or the element’s title)link– An anchor tag made up of the link URL andlabelelement– The linked element, if applicable
{% if entry.myLinkField.element %}
{{ entry.myLinkField.link }}
{% else %}
<a href="{{ entry.myLinkField }}" target="_blank" rel="noopener">
{{ entry.myLinkField.label }}
</a>
{% endif %}
Registering custom link types
Additional link types can be registered via the EVENT_REGISTER_LINK_TYPES event. Link types are defined as classes which extend one of the following base classes:
craft\fields\linktypes\BaseLinkTypecraft\fields\linktypes\BaseElementLinkType(for element link types)craft\fields\linktypes\BaseTextLinkType(for textual link types)
Here’s a how to register a link type for a custom element type:
// Plugin.php
use craft\events\RegisterComponentTypesEvent;
use craft\fields\Link;
use modules\foo\AssetLinkType;
use yii\base\Event;
Event::on(
Link::class,
Link::EVENT_REGISTER_LINK_TYPES,
function(RegisterComponentTypesEvent $event
) {
$event->types[] = MyElementLinkType::class;
});
// MyElementLinkType.php
use craft\fields\linktypes\BaseElementLinkType;
abstract class MyElementLinkType extends BaseElementLinkType
{
protected static function elementType(): string
{
return MyElementType::class;
}
protected function availableSourceKeys(): array
{
return [
// list the source keys that contain elements that have URLs
// ...
];
}
protected function selectionCriteria(): array
{
return array_merge(parent::selectionCriteria(), [
// ...
]);
}
}
Notes
craft\fields\Urlhas been aliased tocraft\fields\Link, so existing URL fields will be switched to Link automatically, and any code references toUrlwill continue to work.- Link fields do not have the ability to show settings to control
target, label, etc. Those can be captured via separate custom fields.
Related issues
- #9062
- #9916
- #14962
- #11637
This is awesome, thanks a lot Brandon.
Pretty much the only thing I'd hope to see added to this, is some way of accessing the actual element selected, in links using the BaseElementLinkType class.
While I think it's fine that Link fields doesn't expose an input for labels/link text, it'd be great (and would eliminate some AX friction) if it was possible to do something like this, in order to have element links' texts/labels default to the selected element's title:
{% if entry.myLinkField.type == 'element-entry' %}
<a href="{{ entry.myLinkField }}">{{ entry.myLinkLabelField | default(entry.myLinkField.element.title) }}</a>
{% else %}
<a href="{{ entry.myLinkField }}" target="_blank" rel="noopener">
{{ entry.myLinkLabelField }}
</a>
{% endif %}
Alternatively, instead of exposing the element for BaseElementLinkType via something like myLinkField.element, maybe the BaseLinkType class could implement something like a getText() method, that returns the value (i.e. URL) for the base class, the selected element's title for the BaseElementLinkType, and can be overridden to return whatever for custom link types.
So glad to finally see this and a way to register custom Elements Link Types.
Links started the internet! They will feel so at home in a CMS.
Link fields do not have the ability to show settings to control target, label, etc. Those can be captured via separate custom fields.
I assume you're thinking multiple links would be a matrix field with a block that contains the link field and the overrides.
@leevigraham That or something like #14600.
@mmikkel Both good ideas, so just added them both. Updated the PR description with:
The following properties are also available off of the value in Twig templates:
type– The link type’s ID (url,category,entry, ortel)label– A suggested label that could be used in anchor links (e.g. the URL sans-schema, or the element’s title)link– An anchor tag made up of the link URL andlabelelement– The linked element, if applicable{% if entry.myLinkField.element %} {{ entry.myLinkField.link }} {% else %} <a href="{{ entry.myLinkField }}" target="_blank" rel="noopener"> {{ entry.myLinkField.label }} </a> {% endif %}
@brandonkelly Very good addition 🎉
One thing we have used a lot with Typed Link Field and now Hyper is the ability to append something (a fragment or query parameters) to entry links. For example, you want to link to a specific section on a specific entry, so you select the entry and enter the fragment for the section on that page. Or you want to link to a search page with pre-selected filters or a search term, in this case you would enter an additional query string. Would it be possible to support this for element links?
There's still a use-case for Hyper, which supports full field layouts and creating multiple links in one field. But appending something to entry URLs is much more common, so this would be nice to have as a core feature.
This is awesome and much appreciated! I don't see it replacing Hyper (yet?), but at the very least it will solve for a lot of basic scenarios. Thank you for listening to community feedback and getting out a workable solution instead of waiting for multi-element-type sources. ❤️
@MoritzLost I don’t see that feature in Hyper. You must be capturing the fragment with a custom field?
@MoritzLost I don’t see that feature in Hyper. You must be capturing the fragment with a custom field?
@brandonkelly No, it's a native attribute (urlSuffix) in Hyper (mentioned here in passing). It's not placed in the field layout by default for new fields, but can be added to the field layout for every link type:
In Typed Link Field it's an option for every link type, this results in an additional text input next to the URL / entry selector:
@MoritzLost Gotcha… still, that could pretty easily be added with an adjacent custom field, just like “Open in a new window” etc.
@brandonkelly Would it also make sense to include linking to assets? At least that is a feature that I would be using quite a bit when a button links to a PDF file.
@droemmelbert I decided not to initially because it seemed unlikely that there’s a need to link to assets or a webpage URL; more likely you’d just want a dedicated field just for linking to an asset, at which point you’d be better off using an Assets field, which would be much more specialized than Link (fine-tuned control over available sources, file types, permission enforcement, plus direct-to-field upload support).
If I’m wrong and there is a legitimate need for a field that links to both webpage URLs and assets, I can consider pulling those features in.
@droemmelbert I decided not to initially because it seemed unlikely that there’s a need to link to assets or a webpage URL; more likely you’d just want a dedicated field just for linking to an asset, at which point you’d be better off using an Assets field, which would be much more specialized than Link (fine-tuned control over available sources, file types, permission enforcement, plus direct-to-field upload support).
If I’m wrong and there is a legitimate need for a field that links to both webpage URLs and assets, I can consider pulling those features in.
I think it’s worth including. Consider a multi-purpose component such as a button in the hero or a CTA on a page. Sometimes those get used to link to forms, sometimes they get linked to downloadables, such as PDFs. I typically enable it as an option by default to prevent people from pasting a URL directly to an asset rather than asking a developer to change it.
I also think assets are definitely worth including. FWIW, clients link to assets in CKEditor fields all the time, e.g. to create links for downloading brand materials, etc.
Honestly, the "link" field is almost always a "button" field, and yup... clients "link to" assets, so I'd be down for Assets as well.
Asset link type option added 🎉
Required some refactoring—link types get instantiated now, and can define settings. All element type-based link types now show a “Sources” setting, allowing you to fine tune which sources should be available in element selection modals.
The asset link type also has “Allowed File Types”, “Show unpermitted volumes”, and “Show unpermitted files” settings, similar to Assets fields.
Uploading directly to the field isn’t supported, as that would add a huge amount of complexity and be a pretty big departure from other link type UIs. (It’s possible to upload within the asset selection modal though.)
Very Good news.
Will there be Support for Sites, Products (Craft Commerce) and Product Variants (Craft Commerce)?
Why not adding a Multi Type Field like an Entry Field? A Field Type in which every Type of Craft CMS native Element can be included? Like Entry, Category, Asset, Product, Site, Product Variant, and so on.?
Great news....really pleased to see this being added, should be a great addition! One question - will there be anything in place to help migrate data from some of those older systems such as linkfield etc into this? One of the big holdbacks we have to upgrading to Craft 5 is that some sites have all the link data in those plugins and an upgrade would mean going through the entire site and re-populating links...
@alexanderbuergin Yes to products; no to variants (variants don’t have URIs). I hadn’t considered sites but I guess they could be an option.
Why not adding a Multi Type Field like an Entry Field? A Field Type in which every Type of Craft CMS native Element can be included? Like Entry, Category, Asset, Product, Site, Product Variant, and so on.?
There is a small amount of work involved for each element type (defining settings, defining sources that should be available to select from, defining the selectable element criteria, etc.), so we can’t just add every element type automatically.
@splendidrob Good question. I’m guessing it will be possible to write a script for it. I’m not totally sure where that should live, besides probably not directly within Craft.
Is it possible to access the link label field via graphql?
@mark-reason It will be in Craft 5.6 (#16237).