Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Form] Allow ChoiceType to select from tree-like structures #3835

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
webmozart opened this issue Apr 8, 2012 · 9 comments
Closed

[Form] Allow ChoiceType to select from tree-like structures #3835

webmozart opened this issue Apr 8, 2012 · 9 comments

Comments

@webmozart
Copy link
Contributor

Sometimes it would be nice to allow the user to select from a tree structure, such as a

  • root directory with subdirectories and their subdirectories,
  • menu and submenu (where to add new page),
  • regions, districts and their cities (region or district can be also selected),
  • tree of payment methods (direct payment methods like PayPal,CardPay, offline payment methods...),
  • tree of categories in eshop (where to add new product).

Implementation suggestion: a TreeChoiceList

Origin of this issue: #3456

@j
Copy link

j commented Apr 10, 2012

+1 for the TreeChoiceList option - I posted about this almost a year ago #1333

@raphox
Copy link

raphox commented Jan 15, 2013

To insert attributes in the options I have created a new type of widget and override theme of the block choice_widget_options. See the code used below.

# Labone\Bundle\OrderBundle\Form\RequestProductType.php
...
class RequestProductType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
                ->add('product', 'labone_entity_product', array(
                    'class' => "Labone\Bundle\ProductBundle\Entity\Product",
                    'attr' => array('class' => "chosen_find input-xlarge")
                ))
# Labone\Bundle\OrderBundle\Form\Type\LaboneEntityProductType.php
...
class LaboneEntityProductType extends AbstractType
{

    public function getParent()
    {
        return 'entity';
    }

    public function getName()
    {
        return 'labone_entity_product';
    }

    /**
     * {@inheritdoc}
     */
    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        foreach ($view->vars['choices'] as $choice) {
            $choice->attr = array_replace(isset($choice->attr) ? $choice->attr : array(), array(
                'data-price_unitary' => $choice->data->getPrice()
            ));
        }
    }

}
# choice_widget_options.html.twig
{% block choice_widget_options %}
{% spaceless %}
    {% for group_label, choice in options %}
        {% if choice is iterable %}
            <optgroup label="{{ group_label|trans({}, translation_domain) }}">
                {% set options = choice %}
                {{ block('choice_widget_options') }}
            </optgroup>
        {% else %}
            <option value="{{ choice.value }}"{% if choice is selectedchoice(value) %} selected="selected"{% endif %}
            {% if choice.attr is defined %}
                {% for attrname, attrvalue in choice.attr %}{% if attrname in ['title'] %}{{ attrname }}="{{ attrvalue|trans({}, translation_domain) }}" {% else %}{{ attrname }}="{{ attrvalue }}" {% endif %}{% endfor %}
            {% endif %}
            >{{ choice.label|trans({}, translation_domain) }}</option>
        {% endif %}
    {% endfor %}
{% endspaceless %}
{% endblock choice_widget_options %}

observer with the snippet code:

 {% for attrname, attrvalue in choice.attr %}...{% endfor %}

and see change in base block form_div_layout.html.twig#L8.

# Labone/Bundle/OrderBundle/Resources/cofig/webservice.yml
services:
  labone_order.form.type.entity_product:
    class: Labone\Bundle\OrderBundle\Form\Type\LaboneEntityProductType
    tags:
      - { name: form.type, alias: labone_entity_product }

@stof
Copy link
Member

stof commented Aug 18, 2014

@webmozart what do you think about this feature request now ?

@liverbool
Copy link
Contributor

👍

@guilleferrer
Copy link

I have the same issue here but I need to show the form with the "expanded" + "multiple" option : using checkboxes. So I need a tree of checkboxes.

In my case I cannot use "choice_widget_options" block. Any suggestion ?

@sergiostrampelli
Copy link

👍

@mdzzohrabi
Copy link

i create this lazy FormType for this issue. my entities has parent and childs getters.

class EntityTreeType extends AbstractType {

    public function buildView( FormView $view , FormInterface $form , array $options ) {

        $choices = [];

        foreach ( $view->vars['choices'] as $choice ) {
            $choices[] = $choice->data;
        }

        $choices = $this->buildTreeChoices( $choices );

        $view->vars['choices'] = $choices;

    }

    protected function buildTreeChoices( $choices , $level = 0 ) {

        $result = array();

        foreach ( $choices as $choice ){

            $result[] = new ChoiceView(
                str_repeat( '-' , $level ) . ' ' . $choice->getName(),
                $choice->getId(),
                $choice,
                []
            );

            if ( !$choice->getChilds()->isEmpty() )
            $result = array_merge(
                $result,
                $this->buildTreeChoices( $choice->getChilds() , $level + 1 )
            );

        }

        return $result;

    }

    public function setDefaultOptions( OptionsResolverInterface $resolver ) {
        $resolver->setDefaults(array(
            'query_builder' => function ( EntityRepository $repo ) {
                return $repo->createQueryBuilder('e')->where('e.parent IS NULL');
            }
        ));
    }

    public function getParent() {
        return 'entity';
    }

    /**
     * Returns the name of this type.
     *
     * @return string The name of this type
     */
    public function getName()
    {
        return 'entity_tree';
    }
}

View output like this for options :

Item 1
- Child Item 1
Item 2
- Child Item 2
-- Child Item 3

@swietek
Copy link

swietek commented Oct 27, 2016

I think the constructor of ChoiceView changed.
Therefore you should adapt the lines from line 36 to

$result[] = new ChoiceView(
                    $choice,
                    $choice->getId(),
                    str_repeat( '-' , $level ) . ' ' . $choice->getName(),
                    []
                );

@fabpot
Copy link
Member

fabpot commented Sep 21, 2018

Closing this old (6 years old) feature request as nobody ever worked on an actual implementation.

@fabpot fabpot closed this as completed Sep 21, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants