title: Symfony + bootstrap custom form
body: <p>I am trying to make custom  theme for symfony forms with bootstrap.
  Final result looks like this <a href="https://i.stack.imgur.com/avTvQ.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/avTvQ.png" alt="image"></a></p>
  
  <p>Problems:</p>
  
  <ul>
  <li><p>Button and input with token are not in form(loook at html code below)
  Why and how to fix it? </p></li>
  <li><p>Strange glitch happens when i try to add 2 dropzone forms in main form. The first form just disappears. So i need to put empty form before first form.</p></li>
  <li><p>Is it possible to make droplist with checkboxes in symfony? "Simple way" for me is to make ajax request to server from client,
  get data, put data to droplist, than use datatransformer for that
  droplist input. Is there really simple way to make something like
  <a href="https://select2.github.io/examples.html#tags" rel="nofollow noreferrer">this</a> ?</p></li>
  </ul>
  
  <p><a href="https://i.stack.imgur.com/zRt5a.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/zRt5a.png" alt="enter image description here"></a></p>
  
  <p>Html code when browser renders page:</p>
  
  <pre><code>&lt;div class="container"&gt;
  &lt;form name="quest" method="post" class="form-horizontal"&gt;
  ...
  &lt;/form&gt;
  
  &lt;div&gt;&lt;button type="submit" id="quest_save" name="quest[save]"&gt;Отправить&lt;/button&gt;&lt;/div&gt;
  
  &lt;input value="tokenpart_W2u3ooA5-G0-tokenpart" id="quest__token" name="quest[_token]" type="hidden"&gt;
  &lt;/div&gt;
  </code></pre>
  
  <p>html.twig</p>
  
  <pre><code>&lt;div class="container"&gt;
          {{ form_start(form, {'attr': {'class': 'form-horizontal'}}) }}
          {{ form_errors(form) }}
          &lt;div class="form-group"&gt;
              {{ form_label(form.name, null, {'label_attr': {'class': 'col-sm-2 control-label'}}) }}
              &lt;div class="col-sm-10"&gt;
                  {{ form_errors(form.name) }}
                  {{ form_widget(form.name, {'attr': {'class': 'form-control'}}) }}
              &lt;/div&gt;
          &lt;/div&gt;
          &lt;div class="form-group"&gt;
              {{ form_label(form.description, null,{'label_attr': {'class': 'col-sm-2 control-label'}}) }}
              &lt;div class="col-sm-10"&gt;
                  {{ form_errors(form.description) }}
                  {{ form_widget(form.description, {'attr': {'class': 'form-control','rows':'3'}}) }}
              &lt;/div&gt;
          &lt;/div&gt;
          &lt;div class="form-group"&gt;
              {{ form_label(form.city, null,{'label_attr': {'class': 'col-sm-2 control-label'}}) }}
              &lt;div class="col-sm-10"&gt;
                  {{ form_errors(form.city) }}
                  {{ form_widget(form.city, {'attr': {'class': 'form-control'}}) }}
              &lt;/div&gt;
          &lt;/div&gt;
          &lt;div class="form-group"&gt;
              {{ form_label(form.organizer, null,{'label_attr': {'class': 'col-sm-2 control-label'}}) }}
              &lt;div class="col-sm-10"&gt;
                  {{ form_errors(form.organizer) }}
                  {{ form_widget(form.organizer, {'attr': {'class': 'form-control'}}) }}
              &lt;/div&gt;
          &lt;/div&gt;
          &lt;div class="form-group"&gt;
              {{ form_label(form.address, null,{'label_attr': {'class': 'col-sm-2 control-label'}}) }}
              &lt;div class="col-sm-10"&gt;
                  {{ form_errors(form.address) }}
                  {{ form_widget(form.address, {'attr': {'class': 'form-control'}}) }}
              &lt;/div&gt;
          &lt;/div&gt;
          &lt;div class="form-group"&gt;
              {{ form_label(form.metro, null,{'label_attr': {'class': 'col-sm-2 control-label'}}) }}
              &lt;div class="col-sm-10"&gt;
                  {{ form_errors(form.metro) }}
                  {{ form_widget(form.metro, {'attr': {'class': 'form-control'}}) }}
              &lt;/div&gt;
          &lt;/div&gt;
          &lt;div class="form-group"&gt;
              {{ form_label(form.phone, null,{'label_attr': {'class': 'col-sm-2 control-label'}}) }}
              &lt;div class="col-sm-10"&gt;
                  {{ form_errors(form.phone) }}
                  {{ form_widget(form.phone, {'attr': {'class': 'form-control'}}) }}
              &lt;/div&gt;
          &lt;/div&gt;
          &lt;div class="form-group"&gt;
              {{ form_label(form.mail, null,{'label_attr': {'class': 'col-sm-2 control-label'}}) }}
              &lt;div class="col-sm-10"&gt;
                  {{ form_errors(form.mail) }}
                  {{ form_widget(form.mail, {'attr': {'class': 'form-control'}}) }}
              &lt;/div&gt;
          &lt;/div&gt;
          &lt;div class="form-group"&gt;
              &lt;label class="col-sm-2 control-label"&gt;Цена&lt;/label&gt;
              {{ form_label(form.minprice, null,{'label_attr': {'class': 'col-sm-2 control-label'}}) }}
              &lt;div class="col-sm-2"&gt;
                  {{ form_errors(form.minprice) }}
                  {{ form_widget(form.minprice, {'attr': {'class': 'form-control'}}) }}
              &lt;/div&gt;
              {{ form_label(form.maxprice, null,{'label_attr': {'class': 'col-sm-2 control-label'}}) }}
              &lt;div class="col-sm-2"&gt;
                  {{ form_errors(form.maxprice) }}
                  {{ form_widget(form.maxprice, {'attr': {'class': 'form-control'}}) }}
              &lt;/div&gt;
          &lt;/div&gt;&lt;!--/form-group--&gt;
          &lt;div class="form-group"&gt;
              &lt;label class="col-sm-2 control-label"&gt;Кол-во игроков&lt;/label&gt;
              {{ form_label(form.minplayers, null,{'label_attr': {'class': 'col-sm-2 control-label'}}) }}
              &lt;div class="col-sm-2"&gt;
                  {{ form_errors(form.minplayers) }}
                  {{ form_widget(form.minplayers, {'attr': {'class': 'form-control'}}) }}
              &lt;/div&gt;
              {{ form_label(form.maxplayers, null,{'label_attr': {'class': 'col-sm-2 control-label'}}) }}
              &lt;div class="col-sm-2"&gt;
                  {{ form_errors(form.maxplayers) }}
                  {{ form_widget(form.maxplayers, {'attr': {'class': 'form-control'}}) }}
              &lt;/div&gt;
          &lt;/div&gt;&lt;!--/form-group--&gt;
          &lt;div class="form-group"&gt;
              {{ form_label(form.bookinglink, null,{'label_attr': {'class': 'col-xs-2 control-label'}}) }}
              &lt;div class="col-sm-10"&gt;
                  {{ form_errors(form.bookinglink) }}
                  {{ form_widget(form.bookinglink, {'attr': {'class': 'form-control'}}) }}
              &lt;/div&gt;
          &lt;/div&gt;
          &lt;div class="form-group"&gt;
              {{ form_label(form.tags, null,{'label_attr': {'class': 'col-sm-2 control-label '}}) }}
              &lt;div class="col-sm-10"&gt;
                  {{ form_errors(form.tags) }}
                  {{ form_widget(form.tags, {'attr': {'class': 'form-control '}}) }}
              &lt;/div&gt;
          &lt;/div&gt;
          &lt;div class="form-group"&gt;
              {{ form_label(form.mainphoto) }}
              &lt;div class="col-sm-10"&gt;
                  {{ form_errors(form.mainphoto) }}
                  {{ form_widget(form.mainphoto) }}
              &lt;/div&gt;
          &lt;/div&gt;
          &lt;div class="form-group"&gt;
              {{ form_label(form.photos) }}
              &lt;div class="col-sm-10"&gt;
                  {{ form_errors(form.photos) }}
                  {{ form_widget(form.photos) }}
              &lt;/div&gt;
          &lt;/div&gt;
  
          &lt;div class="form-group"&gt;
              &lt;label class="col-sm-2 control-label"&gt;Изображения&lt;/label&gt;
              &lt;div class="col-sm-5 "&gt;
                  &lt;div class="panel panel-default myPanel"&gt;
                      &lt;div class="panel-heading"&gt;Главное фото&lt;/div&gt;
                      &lt;div class="panel-body"&gt;
                          &lt;form &gt;&lt;/form&gt;
                          &lt;form action="{{ oneup_uploader_endpoint('gallery') }}"
                                id="DropZoneForQuestMainPhoto" class="dropzone" method="post"&gt;
                              &lt;input type="hidden" name="typeOfDropzone" value="DropZoneForQuestMainPhoto" /&gt;
                          &lt;/form&gt;
  
                      &lt;/div&gt;
                  &lt;/div&gt;
               &lt;/div&gt;
              &lt;div class="col-sm-5"&gt;
                  &lt;div class="panel panel-default myPanel"&gt;
                      &lt;div class="panel-heading"&gt;Галерея&lt;/div&gt;
                      &lt;div class="panel-body"&gt;
                          &lt;form action="{{ oneup_uploader_endpoint('gallery') }}"
                                id="DropZoneForQuestGallery" class="dropzone" method="post"&gt;
                              &lt;input type="hidden" name="typeOfDropzone" value="DropZoneForQuestGallery" /&gt;
                          &lt;/form&gt;
                      &lt;/div&gt;
                  &lt;/div&gt;
              &lt;/div&gt;
          &lt;/div&gt;&lt;!--/form-group--&gt;
      {{ form_end(form) }}
  &lt;/div&gt;
  </code></pre>
  
  <p>formType.php</p>
  
  <pre><code>class formType extends AbstractType
  {
  
      private $manager;
      protected $em;
  
      public function __construct(ObjectManager $manager) {
          $this-&gt;manager = $manager;
      }
      public function buildForm(FormBuilderInterface $builder, array $options)
      {
          $builder
              -&gt;add('name', TextType::class,array(
                  'label' =&gt; 'Название квеста',
                  'attr' =&gt; array(
                      'placeholder'=&gt;"Название квеста",
                          'help'  =&gt; 'Task name should be short and actionable'
                        )))
              -&gt;add('description', TextareaType::class,array(
                  'label' =&gt; 'Описание',
                  'attr' =&gt; array(
                      'placeholder'=&gt;"Описание",
                  )))
              -&gt;add('organizer',EntityType::class,array(
                  'label' =&gt; 'Организатор',
                  'class' =&gt; 'AppBundle:Organizer',
                  'choice_label' =&gt; 'name',
                  'empty_data'=&gt; 'choose',
  
                  'attr' =&gt; array(
                      'class'=&gt;'cityDroplist form-control',
                      'placeholder' =&gt; "Выберите квест",
                      )))
              -&gt;add('city',EntityType::class,array(
                  'label' =&gt; 'Город',
                  'class' =&gt; 'AppBundle:City',
                  'placeholder' =&gt; "Выберите город",
                  'choice_label' =&gt; 'name',
                  'attr' =&gt; array('class'=&gt;'cityDroplist form-control')))
              -&gt;add('address', TextType::class,array('label' =&gt; 'Адрес',
                  'attr' =&gt; array(
                      'placeholder'=&gt;"Адрес",
                  )))
              -&gt;add('metro', TextType::class,array('label' =&gt; 'Метро',
                  'attr' =&gt; array(
                      'placeholder'=&gt;"Метро",
                  )))
              -&gt;add('phone', TextType::class,array('label' =&gt; 'Телефон',
                  'attr' =&gt; array(
                      'placeholder'=&gt;"Телефон",
                  )))
              -&gt;add('mail', TextType::class,array(
                  'label' =&gt; 'Почта',
                  'attr' =&gt; array(
                      'placeholder'=&gt;"Почта",
                  )))
              -&gt;add('minplayers', TextType::class,array(
                  'label' =&gt; false,
                  'attr' =&gt; array(
                      'placeholder' =&gt; 'Min',
                  )))
              -&gt;add('maxplayers', TextType::class,array(
                  'label' =&gt;false,
                  'attr' =&gt; array(
                      'placeholder' =&gt; 'Max',
                      )))
              -&gt;add('minprice', TextType::class,array(
                  'label' =&gt; false,
                  'attr' =&gt; array(
                      'placeholder' =&gt; 'Min',
                  )))
              -&gt;add('maxprice', TextType::class,array(
                  'label' =&gt; false,
                  'attr' =&gt; array(
                      'placeholder' =&gt; 'Max',
                  )))
              -&gt;add('bookinglink', TextType::class,array(
                  'label' =&gt; 'Ссылка на бронирование',
                  'attr' =&gt; array(
                      'placeholder' =&gt; 'Ссылка на бронирование',
                  )))
              -&gt;add('photos',HiddenType::class,array(
                  'label'=&gt;false,
                  'required' =&gt; false))
              -&gt;add('mainphoto',HiddenType::class,array(
                  'label'=&gt;false,
                  'required' =&gt; false,
                  'attr' =&gt; array(
                  )))
              -&gt;add('tags',EntityType::class,array(
                  'label' =&gt; 'Tag',
                  'class' =&gt; 'AppBundle:Tag',
                  'choice_label' =&gt; 'name',
                  'expanded' =&gt; true,
                  'multiple' =&gt; true,
                  ))
              -&gt;add('save', SubmitType::class, array('label' =&gt; 'Отправить'));
  
  
              $builder-&gt;get('photos')
                  -&gt;addModelTransformer(new IssueToNumberTransformer($this-&gt;manager));
              $builder-&gt;get('mainphoto')
                  -&gt;addModelTransformer(new formNumberToUploadedFile($this-&gt;manager));
  
      }
  
  }
  </code></pre>