gbere
8/4/2014 - 6:21 PM

AccountType.php

<?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();
    }
}
{# 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;

/**
 * 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\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\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()));
    }

}
<?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";
    }

}