Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
<?php
namespace NoxLogic\DemoBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Account
*
* @ORM\Table()
* @ORM\Entity()
*/
class Account
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* @ORM\ManyToOne(targetEntity="City")
*/
protected $city;
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* @param string $name
* @return Account
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set city
*
* @param \NoxLogic\DemoBundle\Entity\City $city
* @return Account
*/
public function setCity(\NoxLogic\DemoBundle\Entity\City $city = null)
{
$this->city = $city;
return $this;
}
/**
* Get city
*
* @return \NoxLogic\DemoBundle\Entity\City
*/
public function getCity()
{
return $this->city;
}
}
<?php
namespace NoxLogic\DemoBundle\Form\Type;
use Doctrine\ORM\EntityManager;
use NoxLogic\DemoBundle\Entity\Province;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class AccountType extends AbstractType {
protected $em;
function __construct(EntityManager $em)
{
$this->em = $em;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
// Name of the user
$builder->add('name', 'text');
/* Add additional fields... */
$builder->add('save', 'submit');
// Add listeners
$builder->addEventListener(FormEvents::PRE_SET_DATA, array($this, 'onPreSetData'));
$builder->addEventListener(FormEvents::PRE_SUBMIT, array($this, 'onPreSubmit'));
}
protected function addElements(FormInterface $form, Province $province = null) {
// Remove the submit button, we will place this at the end of the form later
$submit = $form->get('save');
$form->remove('save');
// Add the province element
$form->add('province', 'entity', array(
'data' => $province,
'empty_value' => '-- Choose --',
'class' => 'NoxLogicDemoBundle:Province',
'mapped' => false)
);
// Cities are empty, unless we actually supplied a province
$cities = array();
if ($province) {
// Fetch the cities from specified province
$repo = $this->em->getRepository('NoxLogicDemoBundle:City');
$cities = $repo->findByProvince($province, array('name' => 'asc'));
}
// Add the city element
$form->add('city', 'entity', array(
'empty_value' => '-- Select a province first --',
'class' => 'NoxLogicDemoBundle:City',
'choices' => $cities,
));
// Add submit button again, this time, it's back at the end of the form
$form->add($submit);
}
function onPreSubmit(FormEvent $event) {
$form = $event->getForm();
$data = $event->getData();
// Note that the data is not yet hydrated into the entity.
$province = $this->em->getRepository('NoxLogicDemoBundle:Province')->find($data['province']);
$this->addElements($form, $province);
}
function onPreSetData(FormEvent $event) {
$account = $event->getData();
$form = $event->getForm();
// We might have an empty account (when we insert a new account, for instance)
$province = $account->getCity() ? $account->getCity()->getProvince() : null;
$this->addElements($form, $province);
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'NoxLogic\DemoBundle\Entity\Account'
));
}
public function getName()
{
return "account_type";
}
}
<?php
namespace NoxLogic\DemoBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* City
*
* @ORM\Table()
* @ORM\Entity()
*/
class City
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* @ORM\ManyToOne(targetEntity="Province", inversedBy="cities")
*/
protected $province;
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* @param string $name
* @return City
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set province
*
* @param \NoxLogic\DemoBundle\Entity\Province $province
* @return City
*/
public function setProvince(\NoxLogic\DemoBundle\Entity\Province $province = null)
{
$this->province = $province;
return $this;
}
/**
* Get province
*
* @return \NoxLogic\DemoBundle\Entity\Province
*/
public function getProvince()
{
return $this->province;
}
function __toString() {
return $this->getName();
}
}
<?php
namespace NoxLogic\DemoBundle\Controller;
use NoxLogic\DemoBundle\Entity\Account;
use NoxLogic\DemoBundle\Form\Type\AccountType;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class DefaultController extends Controller
{
public function ajaxAction(Request $request) {
if (! $request->isXmlHttpRequest()) {
throw new NotFoundHttpException();
}
// Get the province ID
$id = $request->query->get('province_id');
$result = array();
// Return a list of cities, based on the selected province
$repo = $this->getDoctrine()->getManager()->getRepository('NoxLogicDemoBundle:City');
$cities = $repo->findByProvince($id, array('name' => 'asc'));
foreach ($cities as $city) {
$result[$city->getName()] = $city->getId();
}
return new JsonResponse($result);
}
public function createAction(Request $request)
{
$account = new Account();
// You probably want to use a service and inject it automatically. For simplicity,
// I'm just adding it to the constructor.
$form = $this->createForm(new AccountType($this->getDoctrine()->getManager()), $account);
$form->handleRequest($request);
if ($form->isValid()) {
/* Do your stuff here */
$this->getDoctrine()->getManager()->persist($account);
$this->getDoctrine()->getManager()->flush();
}
return $this->render('NoxLogicDemoBundle:Default:index.html.twig', array('form' => $form->createView()));
}
}
{# Display the form #}
{{ form(form) }}
{# Add ajax thingie that will update the city select box #}
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="http://code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$('#account_type_province').change(function(){
var val = $(this).val();
$.ajax({
type: "POST",
url: "{{ url('province_ajax_call') }}?province_id=" + val,
success: function(data) {
// Remove current options
$('#account_type_city').html('');
$.each(data, function(k, v) {
$('#account_type_city').append('<option value="' + v + '">' + k + '</option>');
});
}
});
return false;
});
});
</script>
<?php
namespace NoxLogic\DemoBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Province
*
* @ORM\Table()
* @ORM\Entity()
*/
class Province
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* @ORM\OneToMany(targetEntity="City", mappedBy="province")
*/
protected $cities;
/**
* Constructor
*/
public function __construct()
{
$this->cities = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* @param string $name
* @return Province
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Add cities
*
* @param \NoxLogic\DemoBundle\Entity\City $cities
* @return Province
*/
public function addCity(\NoxLogic\DemoBundle\Entity\City $cities)
{
$this->cities[] = $cities;
return $this;
}
/**
* Remove cities
*
* @param \NoxLogic\DemoBundle\Entity\City $cities
*/
public function removeCity(\NoxLogic\DemoBundle\Entity\City $cities)
{
$this->cities->removeElement($cities);
}
/**
* Get cities
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getCities()
{
return $this->cities;
}
function __toString() {
return $this->getName();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.