Hi Roger,

thanks for the answer. I'll try this, I was actually on the right
track.

My only concern is how does the data setting and binding work from
this form to the ContactiInfo entity.
I think that when setData is called the ContactInfo entity will be
queried for the getter or isser for the State field, and I suppose
that your ContactInfo entity does not have a State but contains a City
that has a State reference (i can see that from your preSet data
listener --> $data->getCity()->getState()).

Maybe I got something wrong but I do not see how a State value can be
extracted from the ContactInfo entity and set as the value for the
'state' entity type field (i.e. $builder->add('state',
'entity'  ....). I was unable to get that working in my case; its a
similar case only with car brands e.g. Volvo and car types e.g. C30 --
> a Vehicle has a registration number and a car type, and the car type
has a car brand just as your ContactInfo contains a City which
contains a State.

I will give it another go... maby I overlooked something.

B.R.
Josip




On May 24, 10:39 pm, Roger Webb <webb.ro...@gmail.com> wrote:
> From jmi...@gmail.com
>
> I moved it here so everyone can benefit from the conversation :)
>
> As I learned from my recent issues when I updated to beta 2, here is
> the process.
>
> When the form is created via $this->get('form.factory')->create(new
> MyFormType(), $data), 3 things happen that are relevant to this use-
> case.
>
> 1)  The method setData(null) is called.  Note the null, you have to
> account for this in the preSetData event.
> 2)  setData($data) is called with $data being the second argument of
> create.  Could be an Entity, POPO, or associative array.
> 3)  When we call $form->bindRequest($this->get('request')), the
> preBind event is triggered, the data is an associative array of the
> relevant part of the request.  If your type was "MyType", the array
> returned from $request->get('mytype') is what you get.
>
> Here is josip's email (the full file he requested is below his e-
> mail):
>
> I'm having a similar problem as you had. Since i reckon yours is
> working now I would just like to ask you a few things.
>
> 1) Where does the data['state'] in the preBind listener come from, is
> it an entity field, i.e. an choice field?
> 2) If 1) is true isn't the data['state'] in this  preBInd listener
> actually an identifier of the state entity and not the entity itself
> (i gather that the conversion of the submitted data into its entities
> is complete when the onBindNormData event is fired).
> 3) if 2) is correct did you than load the state entity with an entity
> manager from the given id.
> 4) could you maybe provide me with the complete ContactType form
>
> Thanks in advance
>
> Josip
>
> *****************************************************************************
>
> class ContactInfoType extends AbstractType {
>
>     public function buildForm(FormBuilder $builder, array $options) {
>         $factory = $builder->getFormFactory();
>
>         $refreshCity = function ($form, $state) use ($factory) {
>             $form->add($factory->createNamed('entity', 'city', null,
> array(
>                 'class'         => 'Entity:Cities',
>                 'property'      => 'city_name',
>                 'label'         => 'City',
>                 'query_builder' => function (EntityRepository
> $repository) use ($state) {
>                                        $qb = 
> $repository->createQueryBuilder('cities')
>
>                                                          
> ->select(array('cities', 'zip_codes'))
>
>                                                          
> ->innerJoin('cities.states', 'states')
>
>                                                          -
>
> >innerJoin('cities.zip_codes', 'zip_codes');
>
>                                        if($state instanceof States) {
>                                            $qb = $qb->where('cities.states = 
> :state')
>
>                                                     ->setParameter('state', 
> $state);
>
>                                        } elseif(is_numeric($state)) {
>                                            $qb = $qb->where('states.state_id 
> = :state_id')
>
>                                                     
> ->setParameter('state_id', $state);
>
>                                        } else {
>                                            $qb = $qb->where('states.state_id 
> = 1');
>
>                                        }
>
>                                        return $qb;
>                                    }
>             )));
>         };
>
>         $builder->addEventListener(Events::preSetData, function
> (DataEvent $event) use ($refreshCity) {
>             $form = $event->getForm();
>             $data = $event->getData();
>
>             if($data instanceof ContactInfo) {
>                 $refreshCity($form, $data->getCity()->getState());
>             }
>         });
>
>         $builder->addEventListener(Events::preBind, function
> (DataEvent $event) use ($refreshCity) {
>             $form = $event->getForm();
>             $data = $event->getData();
>
>             if(array_key_exists('state', $data)) {
>                 $refreshCity($form, $data['state']);
>             }
>         });
>
>         $builder->add('first_name', 'text');
>         $builder->add('last_name', 'text');
>         $builder->add('address', 'text');
>
>         $builder->add('state', 'entity', array(
>             'class'         => 'Entity:States',
>             'property'      => 'abbrev',
>             'label'         => 'State',
>             'query_builder' => function (EntityRepository $repository)
> {
>                                    return 
> $repository->createQueryBuilder('states')
>
>                                                      -
>
> >where('states.state_id > 1');
>
>                                }
>         ));
>
>         $builder->add('zip', 'text', array('max_length' => 10));
>         $builder->add('email', 'text');
>     }
>
>     public function getDefaultOptions(array $options) { return
> array('data_class' => 'ARN\EntityBundle\Entity\ContactInfo'); }
>
> }
>
> *****************************************************************************
> On May 5, 8:48 am, Roger Webb <webb.ro...@gmail.com> wrote:
>
>
>
>
>
>
>
> > Hi Bernhard,
>
> > Thank you so much for your reply.  Everything works perfectly.  There
> > was only one thing that needed to be changed.  The data in the
> > "preBind" callback was an associative array instead of a ContactInfo
> > entity.
>
> > Thanks again, I struggled with this form component for a couple of
> > days but I'm really loving it now.
>
> > Roger
>
> > On May 4, 3:15 pm, Bernhard Schussek <bschus...@gmail.com> wrote:
>
> > > HiRoger,
>
> > > You should never rely on the form data in your type class (as you've
> > > just discovered). When the form is constructed, you can never be
> > > certain that the data is already available and won't be changed.
>
> > > In your case, I recommend to add an event listener to the preBind and
> > > preSetData events that overrides the 'city' field.
>
> > >     class ContactType extends AbstractType {
>
> > >        public function buildForm(FormBuilder $builder, array $options) {
> > >            $factory = $builder->getFormFactory();
>
> > >            $refreshCity = function ($form, $state) use ($factory) {
> > >                $form->add($factory->createNamed('entity', 'city', null, 
> > > array(
> > >                    'class' => 'Entity:Cities',
> > >                    'query_builder' => function (EntityRepository
> > > $repository) use ($state) {
> > >                        return $respository->createQueryBuilder('cities')
> > >                            ->select(array('cities', 'zip_codes'))
> > >                            ->innerJoin('cities.zip_codes', 'zip_codes')
> > >                            ->where('cities.states = :state')
> > >                            ->setParameter('state', $state);
> > >                    },
> > >                    'property' => 'city_name',
> > >                    'label' => 'City',
> > >                )));
> > >            };
>
> > >            $builder->addEventListener(Events::preSetData, function
> > > (DataEvent $event) use ($refreshCity) {
> > >                $form = $event->getForm();
> > >                $data = $event->getData();
>
> > >                if ($data instanceof ContactInfo) {
> > >                    $refreshCity($form, $data->getCity()->getState());
> > >                }
> > >            });
>
> > >            $builder->addEventListener(Events::preBind, function
> > > (DataEvent $event) use ($refreshCity) {
> > >                $form = $event->getForm();
> > >                $data = $event->getData();
>
> > >                if (isset($data['state'])) {
> > >                    $refreshCity($form, $data['state']);
> > >                }
> > >            });
>
> > > Obviously this is untested, but I think this should work (with
> > > probably minor modifications depending on your form).
>
> > > Bernhard

-- 
If you want to report a vulnerability issue on symfony, please send it to 
security at symfony-project.com

You received this message because you are subscribed to the Google
Groups "symfony users" group.
To post to this group, send email to symfony-users@googlegroups.com
To unsubscribe from this group, send email to
symfony-users+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/symfony-users?hl=en

Reply via email to