Search code examples
phptwigsymfony-formssymfony6

Symfony form custom theme for collection


I've got a Symfony Form collection and I'm trying to customise how the rendering looks with a custom theme.

It doesn't seem to match on _basket_form_basket_items_widget though. I've verified that the theme is working as it works using integer_widget

But referencing the Symfony Docs, it looks like the above should work?

I've also tried:

_basket_form_basket_items_entry_widget _basket_form_basket_items_qty_widget _basket_form_basket_items_integer_widget _basket_form_integer_widget

# src/templates/form/es_theme.html.twig

{# For view basket form #}
{% block _basket_form_basket_items_widget %}
    <div class="form-group row">
        <label for="{{ id }}" class="col-sm-1 col-form-label">{{ label }}</label>
        <div class="col-sm-11">
            <input type="number" name="{{ full_name }}" class="form-control" id="{{ id }}" min="{{ attr.min }}" value="{{ value }}">
        </div>
    </div>
{% endblock %}
// src/Form/BasketFormType.php

class BasketFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('basketItems', CollectionType::class, [
                'entry_type' => BasketItemQtyOnlyFormType::class,
                'allow_add' => false,
                'allow_delete' => false,
                'label' => null,
                'by_reference' => true,
            ])
        ;
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'data_class' => Basket::class,
        ]);
    }
}
// src/Form/BasketItemQtyOnlyFormType.php

class BasketItemQtyOnlyFormType extends AbstractType
{
    public function __construct(private EntityManagerInterface $em)
    {
    }

    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('qty', IntegerType::class, [
                'label' => 'Quantity',
                'required' => true,
                'row_attr' => ['class' => 'margbott20'],
                'attr' => ['min' => 1],
                'empty_data' => 1,
            ])
        ;
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'data_class' => BasketItem::class,
        ]);
    }
}
# src/templates/basket/index.html.twig

{% for basketFormItem in basketForm.basketItems %}
    {% set basketItem = basketFormItem.vars.value %}

    <div class="basketitem">
        <p class="orange-text">
            <b>
                <a href="{{ path('app_products_product', {'ref': basketItem.product.ref}) }}">{{ basketItem.product.displayName }}</a>
            </b>
        </p>
        <div class="itemline">
            <div class="col-sm-6 nopadding leftcolumn">
                <span class="helper"></span>
                <span>
                    <strong>Code</strong>&nbsp;&nbsp;{{ basketItem.product.ref|replace_keywords }}</span>
                <span class="floatright">
                    {{ form_widget(basketFormItem) }}
                    <a href="{{ path('app_basket_removebasketitem', {basketItem: basketItem.id}) }}" class="btn btn-danger">Remove</a>
                </span>
            </div>
            <div class="col-sm-6 nopadding rightcolumn">
                <span class="helper"></span>
                <span class="leftspan">
                    <strong>Unit price</strong>&nbsp;&nbsp;£{{ productService.getCalculatedUnitPrice(basketItem.product, basketItem.qty) }}</span>
                <span class="floatright">
                    <span class="centered">
                        <strong>Total</strong>&nbsp;&nbsp;£{{ basketService.getBasketItemTotal(basketItem)|round(2)|number_format(2)}}</span>
                </span>
            </div>
            <div class="clearboth"></div>
        </div>
    </div>
{% endfor %}

Solution

  • I managed to solve this.

    I put a var_dump($blockName) in vendor/symfony/twig-bridge/Form/TwigRendererEngine.php in the loadResourceForBlockName function (Symfony 6.2) which then shows all the possible block names.

    The block name I was after is _basket_form_basketItems_entry_qty_widget