e_svirsky
@e_svirsky
Web Developer

Symfony2. Как в форме с коллекцией сделать независимые prototype, для ajax-подгрузки данных?

Symfony2.
Есть форма с единственным полем типа коллекция. В ней type - другая форма. Эта вложенная форма состоит из трёх (компания, страна, язык) полей, каждое из которых - entity. Все они зависимы друг от друга причем подгрузка через ajax. Т.е. выбирая компанию - подгружаются нужные страны, и при выборе страны - нужные языки. По умолчанию (при добавлении нового блока в форме) выбраны первые позиции, т.е. первая компания, соответствующая ей страна и возможные языки.

Всё работает за исключением случая ошибки валидации. К примеру выбрали первую и вторую компанию. У них разные страны и языки. При ошибке симфони пользуется прототипом коллекции, но подгрузить нужно для каждого элемента коллекции свой прототип.

Как сделать разные prototype для каждого элемента коллекции?

Вот этот вариант не подходит, сразу говорю.

Собственно код:

//SettingsType.php
public function buildForm(FormBuilderInterface $builder, array $options)
    {                            
        $builder->add('domains', 'collection', array(
            'type'=> new ArticleSettingsType($this->user, $this->em, $this->request),
            'options'  => array(
                'required'  => false,
                'attr'      => array('class' => 'email-box')
            ),
            'allow_add'=>true,
            'allow_delete'=>true,
            'by_reference' => false,
            'prototype' => true
        ));  
    }


//ArticleSettingsType.php
public function buildForm(FormBuilderInterface $builder, array $options)
    {
        if ($this->request->isMethod('POST')) {
            $settingsAdd =$this->request->get('settingsAdd');
            $oc_ids = array();
            $c_ids = array();
            $l_ids = array();
            if (count($settingsAdd['domains'])) {
                foreach($settingsAdd['domains'] as $s) {
                    if (! in_array($s['company'], $oc_ids)) {
                        $oc_ids[] = $s['company'];
                    }
                    if (! in_array($s['country'], $c_ids)) {
                        $c_ids[] = $s['country'];
                    }
                    if (! in_array($s['languages'], $l_ids)) {
                        $l_ids[] = $s['languages'];
                    }
                }
            }
        } else {
            $oCompanyRepo = $this->em->getRepository('EducationBaseBundle:OperationCompany');
            $aUsersCompanies = $oCompanyRepo->getCompaniesOfUser($this->user);

            $oCountryRepo = $this->em->getRepository('EducationBaseBundle:Country');
            $aCompaniesCountries = $oCountryRepo->getAllByUserAndOperationCompany($this->user, $aUsersCompanies[0]);

            $oLanguageRepo = $this->em->getRepository('EducationBaseBundle:Language');
            $aCountriesLanguages = $oLanguageRepo->getAllByUserAndCountry($this->user, key($aCompaniesCountries[0]));

            $oc_ids = array_values($aUsersCompanies);
            $c_ids = array_map(function($a) {return key($a);}, $aCompaniesCountries);
            $l_ids = array_map(function($a) {return key($a);}, $aCountriesLanguages);
        }

        $this->getBuilderCompany($builder, $oc_ids);
        $this->getBuilderCountry($builder, $c_ids);
        $this->getBuilderLanguage($builder, $l_ids);
    }


Может есть какие мысли?
Спасибо за любую инфу!
  • Вопрос задан
  • 2785 просмотров
Решения вопроса 1
e_svirsky
@e_svirsky Автор вопроса
Web Developer
вынес request с form type. добавил в функции ajax-а функционал.
prototype в этом случае будет одинаковым для всех элементов.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
@neolink
если хотите нормальное решение, то внимательно читайте текст по ссылке что привели сами, передавать request в form_type откровенный говнокод
Ответ написан
BoShurik
@BoShurik Куратор тега Symfony
Symfony developer
Откажитесь от entity в пользу text + DataTranformer.
$builder
    ->add(
        $builder->create('destination', 'text', array(
            'attr' => array(
                'class' => 'select_station'
            )
        ))
        ->addModelTransformer(new EntityToStringTransformer(
                $options['em'],
                'Acme\DemoBundle\Entity\Station',
                'id'
            )
        )
    )
;

В качестве замены селекта на фронтенде рекомендую ivaynberg.github.io/select2
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы