8000 Twig selectedchoice test on custom radio_widget using custom choiceType does not set checked · Issue #13005 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

Twig selectedchoice test on custom radio_widget using custom choiceType does not set checked #13005

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

Closed
webdevilopers opened this issue Dec 16, 2014 · 5 comments
Labels

Comments

@webdevilopers
Copy link

I created a custom form type extending the ChoiceType (entity):

class DormerTypeType extends ChoiceType
{
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'class' => 'Acme\AppBundle\Entity\DormerType',
            'property' => 'name',
            'query_builder' => function(EntityRepository $er) {
                return $er->createQueryBuilder('dt')
                    ->where('dt.available = :available')
                    ->setParameter('available', DormerType::AVAILABLE_TRUE)
                    ->orderBy('dt.name', 'ASC');;
            },
            'expanded' => true,
            'multiple' => false
        ));
    }

    /**
     * {@inheritDoc}
     */
    public function getParent() {
        return 'entity';
    }

    /**
     * {@inheritDoc}
     */
    public function getName() {
        return 'dormerType';
    }
}

Based on the radio widget:
https://github.com/symfony/symfony/blob/2.7/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig#L91-93

I try to define my custom form theme:

{% block dormerType_widget %}
    {% spaceless %}           
        <table cellspacing="2" cellpadding="2" border="0"
            {% for group_label, choice in choices|batch(5) %}
            <tr>
                {% for option in choice %}                    
                <td align="center" valign="bottom">
                    <img src="/images/price-quote/dormer/{{ option.value }}.gif" width="100"><br>                    
                        <input type="radio" {{ block('widget_attributes') }}
                            value="{{ option.value }}"{% if checked == true %} checked="checked"{% endif %}>
                        <label>{{ option.label|trans({}, translation_domain) }}</label>
                </td>
                {% endfor %}
            </tr>                
            {% endfor %}
        </table>
    {% endspaceless %}
{% endblock %}

But I get:
Variable "checked" does not exist

I tried several other attempts as the docs recommend using selectedchoice:

{% if (option is selectedchoice(value)) %}...{% endif %}
{% if (option is selectedchoice(option.value)) %}...{% endif %}
{% if (option is selectedchoice(choice)) %}...{% endif %}

But none of them checking the radio button.

Am I doing something wrong?

Possibly related issues:

< 8000 svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-tag color-fg-inherit">
@fabpot fabpot added the Form label Jan 2, 2015
@webdevilopers
Copy link
Author

In addition, possibly after an Symfony update, I know get an error when submitting the form having selected / checked an option:

Symfony\Component\Validator\ConstraintViolation

Object(Symfony\Component\Form\Form).children[dormerType] = [11 => false, 9 => false, 6 => false, 2 => false, 3 => false, 4 => false, 10 => false, 5 => false, 1 => true]


Caused by:

Symfony\Component\Form\Exception\TransformationFailedException

Unable to reverse value for property path "dormerType": Expected an array.


Caused by:

Symfony\Component\Form\Exception\TransformationFailedException

Expected an array.

Not sure if this is the same or a different issue like #13041.

When removing the custom type the population works fine:

                $builder
                    // Unable to reverse value for property path "dormerType": Expected an array.
                    // Issue: https://github.com/symfony/symfony/issues/13005
                    // Issue: https://github.com/symfony/symfony/issues/13041
//                    ->add('dormerType', 'dormerType', array())
                    ->add('dormerType', 'entity', array(
                        'class' => 'Acme\AppBundle\Entity\DormerType',
                        'expanded' => true,
                        'multiple' => false
                    ));

@webdevilopers
Copy link
Author

I tried setting the property_path to dormerType.id but get an error:
Expected argument of type "object or array", "NULL" given

Stack Trace

    in vendor/symfony/symfony/src/Symfony/Component/PropertyAccess/PropertyAccessor.php at line 232  -
                    // the final value of the path must not be validated
                    if ($i + 1 < $propertyPath->getLength() && !is_object($objectOrArray) && !is_array($objectOrArray)) {
                        throw new UnexpectedTypeException($objectOrArray, 'object or array');
                    }
                    $propertyValues[] = &$propertyValue;
    at PropertyAccessor ->readPropertiesUntil (object(PriceQuoteRequest), object(PropertyPath), '2', true)
    in vendor/symfony/symfony/src/Symfony/Component/PropertyAccess/PropertyAccessor.php at line 58  +
    at PropertyAccessor ->getValue (object(PriceQuoteRequest), object(PropertyPath))
    in vendor/symfony/symfony/src/Symfony/Component/Form/Extension/Core/DataMapper/PropertyPathMapper.php at line 57  +
    at PropertyPathMapper ->mapDataToForms (object(PriceQuoteRequest), object(RecursiveIteratorIterator))
    in vendor/symfony/symfony/src/Symfony/Component/Form/Form.php at line 395  +

Here is the full profiler screen:
dormertype_form_error

I also removed the Assertions from the Entity but that doesn't change anything. Looks like this is really related to the poperty_path accessor.

Instead of using my custom type I used a regular entity type and everything works fine. In biothe cases the HTML from Twig looks similar:

<input id="dormerRequest_dormerType_4" type="radio" checked="checked" value="4" required="required" name="dormerRequest[dormerType]">

<input id="dormerRequest_dormerType" type="radio" value="4" required="required" name="dormerRequest[dormerType]">

No problem here I guess.

Then I commented out the getParent method that was returnin entity. Then I get:
Notice: Undefined index: choice_list

Stack Trace

    in vendor/symfony/symfony/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php at line 45  -
             */
            public function buildForm(FormBuilderInterface $builder, array $options)
            {
                if (!$options['choice_list'] && !is_array($options['choices']) && !$options['choices'] instanceof \Traversable) {
                    throw new LogicException('Either the option "choices" or "choice_list" must be set.');
                }

If I use choice as parent I get:
Notice: Array to string conversion

Does anyone have an idea what is going on here?

@webdevilopers
Copy link
Author

I've just recognized this examle by @superdav42:
#14877 (comment)

I've improved my service class to inject doctrine:

        <service id="acme_demo.form.type.dormerType" class="Acme\AppBundle\Form\Type\Dorm
8000
erTypeType">
            <tag name="form.type" alias="dormerType" />
            <argument type="service" id="doctrine"></argument>
        </service>

The data transformer seems to work fine now. EntityType seemed to be the correct type to extend.

@webdevilopers
Copy link
Author

Whatever I try with Symfony 2.6 I cannot get the radio button checked inside my template:

{% block dormerType_widget %}
    {% spaceless %}

        <table cellspacing="2" cellpadding="2" border="0" class="preisanfrage">
            {% for group_label, choice in choices|batch(5) %}
            <tr>
                {% for option in choice %}
                    {{ dump(option) }}
{% if option is selectedchoice(value) %}XXX{% endif %}
{% if option.value == form.vars.value %}YYY{% endif %}
{{ dump(value) }}
                <td align="center" valign="bottom">
                    <img src="http://static.example.net/images/price-quote/dormer/{{ option.value }}.gif" width="100"><br>
                    <input type="radio" {{ block('attributes') }} {{ block('widget_attributes') }} value="{{ option.value }}"><label>{{ option.label|trans({}, translation_domain) }}</label>
                </td>
                {% endfor %}
            </tr>
            {% endfor %}
        </table>
    {% endspaceless %}
{% endblock %}

Following several attempts from:

But no access. Any idea?

@webdevilopers webdevilopers reopened this Jan 17, 2016
@webdevilopers
Copy link
Author

In the end I found this tutorial:

The main problem was caused by my twig batch filter. Instead of running them on the choices it should be on the form var.

The final solution:

{% block dormerType_widget %}
    {% spaceless %}
        <table cellspacing="2" cellpadding="2" border="0" class="preisanfrage">
            {% for subform in form|batch(5) %}
            <tr>
                {% for child in subform %}
                <td align="center" valign="bottom">
                    <img src="http://static.example.net/images/price-quote/dormer/{{ child.vars.value }}.gif" width="100"><br>
                    {{ form_widget(child) }}
                    {{ form_label(child) }}
                </td>
                {% endfor %}
            </tr>
            {% endfor %}
        </table>
    {% endspaceless %}
{% endblock %}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants
0