Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding HTML per-cell on server side #2315

Closed
dorkyboi opened this issue Feb 6, 2020 · 2 comments
Closed

Adding HTML per-cell on server side #2315

dorkyboi opened this issue Feb 6, 2020 · 2 comments

Comments

@dorkyboi
Copy link

dorkyboi commented Feb 6, 2020

TL;DR use return new HtmlString('your HTML here'); inside ->addColumn() callback.


This is not an issue but rather a notice in case somebody will be in need of this. (#456)

If you ever need to add some HTML (wether its a data-attribute or some inline blocks, no matter) you actually can do so.

Imagine you have UsersDataTable with current structure:

public function dataTable($query) {
    return datatables()
        ->eloquent($query)
        ->addColumn('active', function (User $user) {
            return $user->is_active ? 'Yes' : 'No';
        });
}

protected function getColumns() {
    return [
        Column::make('username')->title('Username'),
        Column::make('is_active')->title('Active'),
    ];
}

What if instead of simple Yes/No i would like to have green/red text color accordingly? One could just make it like so:

return '<span class="text-' . $user->is_active ? 'success' : 'danger' . '">'
    . $user->is_active ? 'Yes' : 'No'
    . '</span>';

but, even though we do {!! $dataTables->html() !!} in our Blades, all HTML would still be encoded by htmlspecialchars.

Solution to this is rather simple: just wrap returning string with HtmlString, like so:

return new HtmlString( '<span class="text-' . $user->is_active ? 'success' : 'danger' . '">'
    . $user->is_active ? 'Yes' : 'No'
    . '</span>');

Well, how does this help you might ask? Lets take a look at e() helper function, that is BTW used by Blade's {{ }} behind the scenes:

/**
 * Encode HTML special characters in a string.
 *
 * @param  \Illuminate\Contracts\Support\Htmlable|string  $value
 * @param  bool  $doubleEncode
 * @return string
 */
function e($value, $doubleEncode = true) {
    if ($value instanceof Htmlable)
        return $value->toHtml();

    return htmlspecialchars($value, ENT_QUOTES, 'UTF-8', $doubleEncode);
}

As you can see, if we supply instace of Htmlable - it is not passed to htmlspecialchars at all. And, as you might have guessed, HtmlString is indeed an instance of Htmlable. Obviously, you are not escaping any potential malicious PHP code that may be in your variables so be mindful.

Hope this helps. Good luck.

@dorkyboi dorkyboi closed this as completed Feb 6, 2020
@yajra
Copy link
Owner

yajra commented Feb 7, 2020

You can also use rawColumns and specify which columns are allowed to return an html content.

@yajra
Copy link
Owner

yajra commented Feb 7, 2020

Another way is to use dataTables renderers and create your custom one.

See https://github.com/yajra/laravel-datatables-assets for some ref. :)

Column::make('deleted_at')->renderJs('badge', null),

@github-actions github-actions bot locked and limited conversation to collaborators Oct 17, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants