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