FilamentIcon::register view() wrongly (?) rendered as image source
I am trying to replace an icon. For example:
tables::actions.filter
In the docs it says:
Alternatively, you may use HTML instead of an icon name to render an icon from a Blade view for example:Source: https://filamentphp.com/docs/3.x/support/icons#replacing-the-default-icons When I pass a
view()
it will load the content as the src
of the img
-element. What I expect to happen here is to replace the entire img
-element by what's in my Blade file.
Is this intended behaviour or is this an issue with Filament?38 Replies
When I pass a view() it will load the content as the src of the img-element.Not sure what that means. Icons probably should be SVG and not
<img>
tags.
Can you share any code? What does your Blade file look like?
Also maybe share a screenshot of what is happeningI use this in my service provider.
The result is:
I thought it would replace the entire image element like so:
The result is it can't find the image because I didn't pass it a url.
I haven’t looked into the code but I guess this is the fallback when it’s not an svg? 🤔
Same issue.
I tried to find the code that does this but couldn't really find it.
would you like to use another heroicon?
I mean
No, I want to specify html
Which should be possible according to https://github.com/filamentphp/filament/blob/3.x/packages/support/resources/views/components/icon.blade.php but when I debug the $icon it's already rendered and is a string at that point so the if-statement that checks if its Htmlable is always false
GitHub
filament/packages/support/resources/views/components/icon.blade.php...
A collection of beautiful full-stack components for Laravel. The perfect starting point for your next app. Using Livewire, Alpine.js and Tailwind CSS. - filamentphp/filament
Trying to debug this. It's already returned as a string from the Action
Seems like you are the first person trying this. The docs were added in December 2023 😅
@Zep Fietje Since you added the docs, do you have any idea how this was supposed to work? We have
HtmlString
in a lot of places but it's missing from Support\Concerns\HasIcon
. Even if we add this: Views aren't HtmlString
s.It's really weird. Because FilamentIcon::resolve returns the Htmlable view in HasFilters but for some reason it's converted to a string in HasIcon even though there's nothing in between.
I tried to add Htmlable to the
icon
method but that didn't change anything.The
$icon
property and all the methods don't accept HtmlString
so it's casted to a string
I forgot to import the Htmlable class, so yea that's the fix
Never knew that, interesting
But does it work with plain
view()
? 🤔
I wrapped it like this: new HtmlString(view('icons.chevron-up')->render()),
It should once Htmlable is added to all the methods
I've only tested it in HasIcon's icon() method for now.
Doesn't work for me. Since
view()
gets casted to string, too, I thinkCreated a PR: https://github.com/filamentphp/filament/pull/13358
GitHub
HasIcon: Support HtmlString and update docs by pxlrbt · Pull Reques...
Description
According to the docs you should be able to pass a view to register an icon alias. This gets casted to a string though and is then outputted as an image.
Also view() doesn't cast to...
Maybe it gets converted at some point because a view does return an Htmlable element
When I test this, I get:
test(): Return value must be of type Illuminate\Support\HtmlString, Illuminate\View\View returned
It's Htmlable
but doesn't return HtmlString
.HtmlString is just a wrapper to create an Htmlable from a string though?
As HtmlString implements Htmlable
Htmlable
is an interface. Not a classThat doesn't matter, Laravel checks if it's an Htmlable element and calls toHtml(), if you check Laravel's source it never checks if something is an HtmlString, it always checks if its Htmlable
But we are in Filament codebase here, not Laravel. And the code you shared above
icon.blade.php
checks for HtmlString
not Htmlable
.
Not sure why we don't use Htmlable
everywhere.Huh, maybe I'm not checking the right file but it's checking for Htmlable
GitHub
filament/packages/support/resources/views/components/icon.blade.php...
A collection of beautiful full-stack components for Laravel. The perfect starting point for your next app. Using Livewire, Alpine.js and Tailwind CSS. - filamentphp/filament
Oh you are right. Okay, we use
Htmlable
there. But all the methods and properties usually use HtmlString
🙈I've done some digging but I think that's unrelated. It seems like passing an Htmlable as a prop to a component renders it. When you use an HtmlString it works. Feels like a bug in Laravel but I can't find how that works.
Yes. That's where I ended up too. The issue is passing it from
action.blade.php
to icon-button.blade.php
. I think we had a workaround for this before, but I am not sure how it works. I CCed Zep in that PRGitHub
framework/src/Illuminate/View/Compilers/Concerns/CompilesComponents...
The Laravel Framework. Contribute to laravel/framework development by creating an account on GitHub.
That's the reason it gets converted. A view has __toString() and HtmlString doesn't.
I'll add it to the PR
Hm, no, that's not it. It's still returned as a string somehow 🤦♂️
What do you mean? What was your change?
In sanitizeComponentAttribute I've added a conditional for Htmlable, that doesn't sanitize the view, but further down the line it's still rendered somehow
That probably won't be a solution for us anyway. It would only work with newer version and might be a breaking change for Laravel
At this point I want to know why this is happening. The workaround of using an html string is fine for me.
GitHub
framework/src/Illuminate/View/View.php at 11.x · laravel/framework
The Laravel Framework. Contribute to laravel/framework development by creating an account on GitHub.
That's the reason it happens. It renders
Renderables
. Views are renderable while Htmlable's are not.Views are Htmlable, right? Not too sure, but maybe the original functionality broke when we fixed another bug the original PR introduced? 😅
Yeah this was one of the bugs: the html icon needs to be passed as slot instead of prop
Doubt this ever worked because actions only return a string no HtmlString.
It never worked for two reasons. A view() is stringable. As the
HasIcon
trait didn't have the Htmlable
type, PHP would convert it to string and render the HTML. After the type was added it didn't work either and that's because a view is also Renderable. If you pass a view to another view as a prop it renders all Renderables.
As a workaround I added the Htmlable types and included this in getIcon
inside the HasIcons
trait:
This looks a bit weird because you're not accepting a renderable, but because a view is both this works.