symfony / ux

Symfony UX initiative: a JavaScript ecosystem for Symfony
https://ux.symfony.com/
MIT License
847 stars 312 forks source link

[Icon] Error when upgrading to 2.21.0 version #2307

Closed javiereguiluz closed 1 week ago

javiereguiluz commented 1 week ago

I have a custom Icon Twig component that basically does this:

{% set arguments = ... %}
{% component 'ux:icon' with arguments %}{% endcomponent %}

In UX Icon 2.20.0 and earlier versions, it works. Starting from 2.21.0, it fails with this error:

An exception has been thrown during the rendering of a template
("Unknown component "ux:icon". Did you mean this: "UX:Icon"?").

If I set it to:

{% component 'UX:Icon' with arguments %}{% endcomponent %}

I see a similar error:

Unable to find template "components/UX/Icon.html.twig"
(looked into: {my_project}/templates, {my_project}/vendor/symfony/twig-bridge/Resources/views/Form).

I also tried {% component 'twig:UX:Icon', {% component 'Twig:UX:Icon', etc. with no effect.


Full stack trace:

InvalidArgumentException:
Unknown component "ux:icon". Did you mean this: "UX:Icon"?

  at vendor/symfony/ux-twig-component/src/ComponentFactory.php:249
  at Symfony\UX\TwigComponent\ComponentFactory->throwUnknownComponentException('ux:icon')
     (vendor/symfony/ux-twig-component/src/ComponentFactory.php:65)
  at Symfony\UX\TwigComponent\ComponentFactory->metadataFor('ux:icon')
     (vendor/symfony/ux-twig-component/src/ComponentFactory.php:73)
  at Symfony\UX\TwigComponent\ComponentFactory->create('ux:icon', array('name' => 'tabler:menu-2', 'aria-hidden' => true, 'font-size' => false))
     (vendor/symfony/ux-twig-component/src/ComponentRenderer.php:89)
  at Symfony\UX\TwigComponent\ComponentRenderer->startEmbeddedComponentRender('ux:icon', array('name' => 'tabler:menu-2', 'aria-hidden' => true, 'font-size' => false), array('name' => 'tabler:menu-2', 'attributes' => object(ComponentAttributes), 'this' => object(AnonymousComponent), 'computed' => object(ComputedPropertiesProxy), 'outerScope' => array(), '__props' => array(), '__context' => array(), 'app' => object(AppVariable), 'size' => null, 'height' => null, 'width' => null, 'class' => null, 'style' => null, 'ariaHidden' => true, 'arguments' => array('name' => 'tabler:menu-2', 'aria-hidden' => true, 'font-size' => false), '__embedded' => true), 'components/Icon.html.twig', 20103649201)
     (vendor/symfony/ux-twig-component/src/Twig/ComponentRuntime.php:60)
  at Symfony\UX\TwigComponent\Twig\ComponentRuntime->startEmbedComponent('ux:icon', array('name' => 'tabler:menu-2', 'aria-hidden' => true, 'font-size' => false), array('name' => 'tabler:menu-2', 'attributes' => object(ComponentAttributes), 'this' => object(AnonymousComponent), 'computed' => object(ComputedPropertiesProxy), 'outerScope' => array(), '__props' => array(), '__context' => array(), 'app' => object(AppVariable), 'size' => null, 'height' => null, 'width' => null, 'class' => null, 'style' => null, 'ariaHidden' => true, 'arguments' => array('name' => 'tabler:menu-2', 'aria-hidden' => true, 'font-size' => false)), 'components/Icon.html.twig', 20103649201)
     (var/cache/dev/twig/03/038e82ec4aa56366a2b9730b1c554281.php:172)
  at __TwigTemplate_77017ef5d1abb0a13080ca76aece8300->doDisplay(array('name' => 'tabler:menu-2', 'attributes' => object(ComponentAttributes), 'this' => object(AnonymousComponent), 'computed' => object(ComputedPropertiesProxy), 'outerScope' => array(), '__props' => array(), '__context' => array(), 'app' => object(AppVariable), 'size' => null, 'height' => null, 'width' => null, 'class' => null, 'style' => null, 'ariaHidden' => true, 'arguments' => array('name' => 'tabler:menu-2', 'aria-hidden' => true, 'font-size' => false)), array())
     (vendor/twig/twig/src/Template.php:393)
  at Twig\Template->yield(array('name' => 'tabler:menu-2', 'attributes' => object(ComponentAttributes), 'this' => object(AnonymousComponent), 'computed' => object(ComputedPropertiesProxy), 'outerScope' => array(), '__props' => array(), '__context' => array(), 'app' => object(AppVariable), array())
     (vendor/twig/twig/src/Template.php:349)
  at Twig\Template->display(array('name' => 'tabler:menu-2', 'attributes' => object(ComponentAttributes), 'this' => object(AnonymousComponent), 'computed' => object(ComputedPropertiesProxy), 'outerScope' => array(), '__props' => array(), '__context' => array()))
     (vendor/twig/twig/src/Template.php:364)
  at Twig\Template->render(array('name' => 'tabler:menu-2', 'attributes' => object(ComponentAttributes), 'this' => object(AnonymousComponent), 'computed' => object(ComputedPropertiesProxy), 'outerScope' => array(), '__props' => array(), '__context' => array()))
     (vendor/symfony/ux-twig-component/src/ComponentRenderer.php:76)
  at Symfony\UX\TwigComponent\ComponentRenderer->render(object(MountedComponent))
     (vendor/symfony/ux-twig-component/src/ComponentRenderer.php:55)
  at Symfony\UX\TwigComponent\ComponentRenderer->createAndRender('Icon', array('name' => 'tabler:menu-2'))
     (vendor/symfony/ux-twig-component/src/Twig/ComponentRuntime.php:51)
  at Symfony\UX\TwigComponent\Twig\ComponentRuntime->render('Icon', array('name' => 'tabler:menu-2'))
     (var/cache/dev/twig/ec/eceee7a31134e3ef7d419c7e28be9899.php:65)

In case you are wondering why I use this instead of just using the normal Icon Twig component.

Some of my icons have class attributes. If I used this:

<twig:ux:icon ... class="{{ class ?? false }}" />

If the user defines class explicitly, then the icon is rendered with that custom class and overrides the original class. That's fine.

But, if the user doesn't define the class prop, then it's like <twig:ux:icon ... class="{{ false }}" /> which in practice removes the class attribute originally defined by the icon. That's wrong.

So, my component has code like this:

{% props
    class = null,
    # ...
%}

{% set arguments = {
    name: name,
    'aria-hidden': ariaHidden,
    'font-size': size ? size ~ 'px' : false,
} %}

{% if class is not null %}
    {% set arguments = arguments|merge({ class: class }) %}
{% endif %}

{# ... #}

{% component 'ux:icon' with arguments %}{% endcomponent %}
smnandre commented 1 week ago

There is no UX:icon component, and i'm not sure we ever documented it (this would be a mistake).

The code you use worked previously but was a side effect caused by a bad implémentation made by.... me.

You can have the same result using the ux_icon() Twig fonction, it should be exactly the same for you.

smnandre commented 1 week ago

Note: I will make a patch as soon as possible to either keep some retro-comparibility or at least improve exception message. I just need one hour of "free time" 🫠

javiereguiluz commented 1 week ago

Simon, thanks a lot for reviewing this. I'd say we could close this as "won't fix". My code worked "by chance", so the break wasn't really a break. I applied your suggestion and now use the ux_icon() function.

Everything works perfectly now. So, I don't think we need to add support for the other obscure notation. Thanks a lot!

smnandre commented 1 week ago

Thank for the update @javiereguiluz .. and for all your help and contributions on this repo ❤️