Type to search columns, filters, options, and extensions.

to navigate · Enter to open · Esc to close

Documentation

Url Column

Render DataTable cells as links from raw URLs, Symfony routes, or per-row callables

UrlColumn renders a cell as an <a> tag. The link target can be read from the cell value directly, generated from a Symfony route, or computed with a per-row callable.

Basic Usage

When the cell value already contains the URL, no extra configuration is needed:

use Pentiminax\UX\DataTables\Column\UrlColumn;

UrlColumn::new('website', 'Website');

Renders as: <a href="https://example.com">https://example.com</a>

Empty Values

When a row has no resolvable URL (a null/empty field, or linkToRoute()/linkToUrl() resolving to nothing for that row), the column renders its plain, escaped text instead of an <a> tag:

UrlColumn::new('website', 'Website');

A row with an empty website value renders as plain text — no href-less anchor. This avoids producing <a href=""></a>, which has no accessible name or purpose and fails WCAG 2.4.4.

This also applies to linkToRoute()/linkToUrl(): when the resolver returns nothing for a particular row, that row falls back to plain text too — the cell’s own value (e.g. a name) is never substituted in as a fake href, since it isn’t a URL at all.

If a use case genuinely needs the old always-render-an-anchor behavior, opt back in with renderEmptyAsAnchor():

UrlColumn::new('website', 'Website')
    ->renderEmptyAsAnchor();

Symfony Route

Use linkToRoute() when the URL should be generated from a Symfony route. The callable receives the original source object (or the row array for inline data).

use App\Entity\User;
use Pentiminax\UX\DataTables\Column\UrlColumn;

UrlColumn::new('email', 'Email')
    ->linkToRoute('admin_user_show', static fn (User $user): array => [
        'id' => $user->getId(),
    ]);

The displayed text stays the column value (email here). Only the href is generated from the route.

Pass a static array when the parameters do not depend on the row:

UrlColumn::new('help', 'Help')
    ->linkToRoute('app_help', ['section' => 'users']);

Custom URL per Row

Use linkToUrl() for external URLs or computed URLs:

use App\Entity\User;
use Pentiminax\UX\DataTables\Column\UrlColumn;

UrlColumn::new('profileLabel', 'Profile')
    ->linkToUrl(static fn (User $user): string => 'https://example.com/u/' . $user->getSlug())
    ->openInNewTab();

linkToUrl() also accepts a static string:

UrlColumn::new('support', 'Support')
    ->setDisplayValue('Contact support')
    ->linkToUrl('/support');

linkToRoute() and linkToUrl() are mutually exclusive — calling one clears the other.

Open in New Tab

UrlColumn::new('website', 'Website')
    ->openInNewTab();

Adds target="_blank" and rel="noopener noreferrer".

Custom Display Text

Use a fixed label instead of the cell value:

UrlColumn::new('profile_url', 'Profile')
    ->setDisplayValue('View profile');

Append a visual indicator that the link opens externally:

UrlColumn::new('website', 'Website')
    ->showExternalIcon();

Protocol Options

Use setDefaultProtocol() to prepend a protocol to values that do not already include one:

UrlColumn::new('website', 'Website')
    ->setDefaultProtocol('https');

With this configuration, a value like example.com is rendered with href="https://example.com" while keeping example.com as the displayed text.

Use allowedProtocols() to render only specific URL protocols as links:

UrlColumn::new('website', 'Website')
    ->allowedProtocols(['http', 'https']);

Values with other protocols are escaped and rendered as plain text. You can combine both options:

UrlColumn::new('website', 'Website')
    ->setDefaultProtocol('https')
    ->allowedProtocols(['https']);

API Reference

MethodDescription
UrlColumn::new(string $name, string $title = '')Creates a new UrlColumn (type: html)
linkToRoute(string $routeName, array|callable|null $params = null)Generate href from a Symfony route. Params can be a static array or a per-row callable.
linkToUrl(string|callable $url)Set href from a static string or a per-row callable. Clears any configured route.
openInNewTab()Add target="_blank" and rel="noopener noreferrer"
setDisplayValue(string $value)Use a fixed label instead of the cell value
showExternalIcon(bool $show = true)Append the external-link icon after the anchor text
setDefaultProtocol(string $protocol)Prepend a protocol to href values that do not already include one
allowedProtocols(array $protocols)Render only URLs with the listed protocols as links
renderEmptyAsAnchor(bool $render = true)Render <a href=""> for rows with no resolvable URL instead of falling back to plain text

Complete Example

use App\Entity\User;
use Pentiminax\UX\DataTables\Attribute\AsDataTable;
use Pentiminax\UX\DataTables\Column\NumberColumn;
use Pentiminax\UX\DataTables\Column\TextColumn;
use Pentiminax\UX\DataTables\Column\UrlColumn;
use Pentiminax\UX\DataTables\Model\AbstractDataTable;

#[AsDataTable(User::class)]
final class UsersDataTable extends AbstractDataTable
{
    public function configureColumns(): iterable
    {
        yield NumberColumn::new('id', 'ID');
        yield TextColumn::new('name', 'Name');
        yield UrlColumn::new('name', 'Profile')
            ->linkToRoute('admin_user_show', static fn (User $user): array => [
                'id' => $user->getId(),
            ]);
        yield UrlColumn::new('website', 'Website')
            ->openInNewTab()
            ->showExternalIcon();
    }

    protected function mapRow(mixed $row): array
    {
        return [
            'id'      => $row->getId(),
            'name'    => $row->getName(),
            'website' => $row->getWebsite(),
        ];
    }
}