wawa
wawa

Reputation: 5066

Symfony form EntityType without preloading

Is there a way to get an EntityType form element in Symfony, that doesn't preload all the entries, but still accepts them?

Background: It's for an image selector, where possibly 1000+ images will be stored. I don't want to put load on the DB, every time the field is rendered. The form has a custom frontend, using hidden fields an Javascript (to load a paged list of images).

The current implementation works, as it should, but as it extends the EntityType it does all the preloading, while when using a ChoiceType the form doesn't accept the values (unless, you give them as choices, which would mean to load all entries from the DB)

----------------------- EDIT -----------------------

I'm working with the suggested bundle. If you feel the need to have your own view (widget) as I do, you can achive that quite easy:

If you use composer, you can simple install all needed files running composer require alsatian/form-bundle dev-master

With the bundle installed you can follow this steps:
First, you have to create your own form field (mine looks like this):

<?php

namespace AppBundle\Form\Fields;

use Symfony\Component\Form\AbstractType;
use Alsatian\FormBundle\Form\ExtensibleEntityType;


class UploadFileType extends AbstractType
{
    /**
      * {@inheritdoc}
      */
    public function getParent() {
        return ExtensibleEntityType::class;
    }

    /**
      * {@inheritdoc}
      */
    public function getName() {
        return 'app_upload_file';
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'app_upload_file';
    }
}

Note: you can put anything you like in getBlockPrefix, just remember what you put there.

Next you need to modify your form theme (doc) and add you own widget:

{%- block app_upload_file_widget -%}
    {{ dump(form) }}{# output some debug info #}
    {% if not expanded %}
        {# example for some fake entries #}
            {% if multiple %}
                <input type="hidden" name="{{ full_name }}" value="1" />
                <input type="hidden" name="{{ full_name }}" value="2" />
                <input type="hidden" name="{{ full_name }}" value="3" />
            {% else %}
                <input type="hidden" name="{{ full_name }}" value="1" />
            {% endif %}
    {% else %}
        {{- block('choice_widget') -}}
    {% endif %}
{%- endblock app_upload_file_widget -%}

Note: Here we need our getBlockPrefix and just add a _widget to it!

Finally, we can add it to one of our forms:

<?php

namespace AppBundle\Form\Admin;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class CompanyType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('logo', \AppBundle\Form\Fields\UploadFileType::class, array(
                'class' => \AppBundle\Entity\File::class,
                'choice_label' => 'originalName',
            ))
        ;
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\Company'
        ));
    }
}

Of course we need to have a join in our entity, for me, it looks something like this:

/**
 * @ORM\ManyToOne(targetEntity="File")
 * @ORM\JoinColumn(name="logo_id", referencedColumnName="id")
 */
private $logo;

I hope, this helps someone, that is in the same situation as I am (:

Upvotes: 2

Views: 2223

Answers (1)

Alsatian
Alsatian

Reputation: 3135

This question comes every 3 days :)

I paste my answer from here:

I wrote a bundle (Alsatian/FormBundle), which does what you want on the server side.

Get the sumitted choices in a Form::PRE_SUBMIT event (also PRE_SET_DATA if you use your form to edit), and reinject these choices to the field.

Upvotes: 4

Related Questions