symfony / ux

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

[LiveComponent] Feature Request: Make #[AsLiveComponent] repeatable #2099

Closed mkrauser closed 3 weeks ago

mkrauser commented 2 months ago

Hey guys!

I have a situation where I need to use in two different paces with the exact same functionality but with different templates. I first tried to extend the original LiveComponent, but that lead to problems with traits (in my case ComponentWithFormTrait).

Does it make sense to make AsLiveComponent repeatable?

I tried this and it worked like charme in my case.

#[AsLiveComponent(name: 'UserForm1', template: 'userform1.html.twig')]
#[AsLiveComponent(name: 'UserForm2', template: 'userform2.html.twig')]
class UserForm
{
...
}

What do you think? 😃

smnandre commented 2 months ago

I'm not sure here..

This would help your current case, but also would remove or current 1 component = 1 class and i'm not entirely sure we want that today.

Also, if we do this, every other attribute in the component would apply to both of your components... and if both classes do the same thing, have the same attributes, props, methods.. it probably should be only one component.

So a few questions here

mkrauser commented 1 month ago

@smnandre

Here are the answers to your questions:

what is the real use case ? (would allow me to fully understand the need)

We have a UserRegistrationForm as LiveComponent and display it on two places on our site. The Layout for these two places is different, but the behaviour is exactly the same.

do you only need the template to change ?

yes

can you pass a key for this and include the correct template from the component view ?

I don't fully understand the question, can you clarify this?

what were the problems you got when you extended the Component

The first issue was, that the form-Variable was not defined in the template, because the ComponentWithFormTrait declares the form private. When I use the traits in the derived class, showing the form works, but when I submit it

The submitForm() method is being called, but the FormView has already been built

smnandre commented 1 month ago

Please correct me if i'm wrong / miss-understand your need .. 😅

Let's say you have a LiveComponent FooBarForm with

You need to represent it in two various ways

What i would do here is create two twig files for the different views..

Something like (pseudo-code)

{# components/_FooBarForm_vertical.html.twig #} 

<section>

   <div>
       <label...>
       <input name=foo .... />
   </div>

   <div>
       <label...>
       <textarea name=bar .... />
   </div>

    <button type="cancel" data- .... >Cancel</button>
    <button type="submit" data- .... >Submit</button>
</section>
{# components/_FooBarForm_horizontal.html.twig #} 

<div style="display:flex"><input type=text name=foo /><texatera name="bar"></textarea></div>

In your component you add a #[LiveProp] string $layout (non writable)

When you call your component in the footer you set the prop

{# layouts/_footer.html.twig #} 

<twig:FooBarForm layout="horizontal" .... />

And in your template, something like

{# components/FooBarForm.html.twig #} 
<div {{ attributes }}>

{% if 'horizontal' == layout %}
    {{ include('components/_FooBarForm_horizontal.html.twig') }}
{% else %}
     {{ include('components/_FooBarForm_vertical.html.twig') }}
{% endif %}

</div>
mkrauser commented 3 weeks ago

@smnandre Yes, that would be possible. I haven't thought of that.

Thanks for the hint!