<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>blog.barros.ws &#187; city picker</title>
	<atom:link href="http://blog.barros.ws/tag/city-picker/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.barros.ws</link>
	<description>web development tips</description>
	<lastBuildDate>Sun, 06 Jun 2010 00:34:52 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Country/State/City picker in Symfony 1.1</title>
		<link>http://blog.barros.ws/2008/10/26/countrystatecity-picker-in-symfony-11/</link>
		<comments>http://blog.barros.ws/2008/10/26/countrystatecity-picker-in-symfony-11/#comments</comments>
		<pubDate>Sun, 26 Oct 2008 14:49:03 +0000</pubDate>
		<dc:creator>Carlos Barros</dc:creator>
				<category><![CDATA[symfony]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[city picker]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://blog.barros.ws/?p=38</guid>
		<description><![CDATA[Have you ever seen those forms where you select a country, then it populates a list of states, then you pick a state and it populate a list of cities? I&#8217;ve seem many of these and I really like them. In one of my past projects I was asked to add a similar form to [...]]]></description>
			<content:encoded><![CDATA[<p>Have you ever seen those forms where you select a country, then it populates a list of states, then you pick a state and it populate a list of cities? I&#8217;ve seem many of these and I really like them. In one of my past projects I was asked to add a similar form to the system, using symfony, and I&#8217;ll show how I accomplished this, making use of the excellent new symfony 1.1 form system. For those who want to see what it looks like before keep on reading, I put very simple sample online <a title="City Picker" href="http://blog.barros.ws/symfony/citypicker" target="_blank">in this link</a>.</p>
<p><span id="more-38"></span></p>
<p>Let&#8217;s start with the database model (config/schema.yml):</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">propel:
  _attributes:   { noXsd: false, defaultIdMethod: none, package: lib.model }
&nbsp;
  cp_users:
    _attributes:     { phpName: User, idMethod: native }
    id:              ~
    name:            { type: varchar(100), required: true }
    country_id:      { type: integer, required: true, foreignTable: cp_countries, foreignReference: id }
    state_id:        { type: integer, required: true, foreignTable: cp_states, foreignReference: id }
    city_id:         { type: integer, required: true, foreignTable: cp_cities, foreignReference: id }
    created_at:      ~
    updated_at:      ~
&nbsp;
  cp_countries:
    _attributes:     { phpName: Country, idMethod: native }
    id:              ~
    code:            { type: varchar(2), required: true }
    name:            { type: varchar(100), required: true }
&nbsp;
  cp_states:
    _attributes:     { phpName: State, idMethod: native }
    id:              ~
    country_id:      { type: integer, required: true, foreignTable: cp_countries, foreignReference: id, onDelete: &quot;CASCADE&quot; }
    name:            { type: varchar(100), required: true }
&nbsp;
  cp_cities:
    _attributes:     { phpName: City, idMethod: native }
    id:              ~
    state_id:        { type: integer, required: true, foreignTable: cp_states, foreignReference: id, onDelete: &quot;CASCADE&quot; }
    name:            { type: varchar(100), required: true }</pre></div></div>

<p>This is a very simple database model, with user, country, state and city. In this schema, each city is related to a single state and each state is related to a single country. You may ask why I did add all these three elements in the user model, as we can get these info from the city. Honestly, there&#8217;s no reason for this, but I left if there just for the sake of simplicity. We can remove state and country and create a getState() and getCountry() methods on User class to get these informations, but I&#8217;ll leave it as an exercise for the readers. So, first step is to build this model and then generate SQL script:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">$ symfony propel:build-model
$ symfony propel:build-sql
$ symfony propel:insert-sql</pre></div></div>

<p>Also, for this example I created a module called citypicker, inside frontend application:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">$ symfony generate:module frontend citypicker</pre></div></div>

<p>First step in this sample is to create the list view, I&#8217;ll not explain in details about it because it&#8217;s just a simple list view with nothing special, I&#8217;ll just put the action and template code here:</p>
<p>actions.class.php:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> executeIndex<span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">users</span> <span style="color: #339933;">=</span> UserPeer<span style="color: #339933;">::</span><span style="color: #004000;">doSelect</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> Criteria<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> executeDel<span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
  	<span style="color: #000088;">$user</span> <span style="color: #339933;">=</span> UserPeer<span style="color: #339933;">::</span><span style="color: #004000;">retrieveByPK</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;id&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  	<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">forward404Unless</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$user</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  	<span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">delete</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  	<span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">redirect</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'citypicker/index'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span></pre></div></div>

<p>indexSuccess.php:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">&lt;table width=&quot;50%&quot; align=&quot;center&quot; border=&quot;1&quot;&gt;
	&lt;tr&gt;
		&lt;th&gt;ID&lt;/th&gt;
		&lt;th align=&quot;left&quot;&gt;Name&lt;/th&gt;
		&lt;th align=&quot;left&quot;&gt;Country&lt;/th&gt;
		&lt;th align=&quot;left&quot;&gt;State&lt;/th&gt;
		&lt;th align=&quot;left&quot;&gt;City&lt;/th&gt;
	&lt;/tr&gt;
	<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$users</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$user</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
		&lt;tr&gt;
			&lt;td align=&quot;center&quot;&gt;<span style="color: #000000; font-weight: bold;">&lt;?=</span>link_to<span style="color: #009900;">&#40;</span><span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'citypicker/edit?id='</span><span style="color: #339933;">.</span><span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span> - <span style="color: #000000; font-weight: bold;">&lt;?=</span>link_to<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'del'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'citypicker/del?id='</span><span style="color: #339933;">.</span><span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/td&gt;
			&lt;td&gt;<span style="color: #000000; font-weight: bold;">&lt;?=</span>esc_entities<span style="color: #009900;">&#40;</span><span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/td&gt;
			&lt;td&gt;<span style="color: #000000; font-weight: bold;">&lt;?=</span><span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCountry</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/td&gt;
			&lt;td&gt;<span style="color: #000000; font-weight: bold;">&lt;?=</span><span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getState</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/td&gt;
			&lt;td&gt;<span style="color: #000000; font-weight: bold;">&lt;?=</span><span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCity</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/td&gt;
		&lt;/tr&gt;
	<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endforeach</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
&lt;/table&gt;
&lt;p align=&quot;center&quot;&gt;<span style="color: #000000; font-weight: bold;">&lt;?=</span>button_to<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'New user'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'citypicker/edit'</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/p&gt;</pre></div></div>

<p>Now we need to create the edit view, where the citipicker will be shown. For this, we need to create the form that will handle user input. In this example I didn&#8217;t use propel:build-forms command, instead I created the form from scratch (that&#8217;s one point to improve). The resulting code is as follows:</p>
<p>lib/form/CPUserForm.class.php:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> CPUserForm <span style="color: #000000; font-weight: bold;">extends</span> sfFormPropel
<span style="color: #009900;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> configure<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
  	<span style="color: #666666; font-style: italic;">// build state criteria</span>
  	<span style="color: #000088;">$stateC</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Criteria<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  	<span style="color: #000088;">$stateC</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">add</span><span style="color: #009900;">&#40;</span>StatePeer<span style="color: #339933;">::</span><span style="color: #004000;">COUNTRY_ID</span><span style="color: #339933;">,</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getObject</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCountryId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  	<span style="color: #666666; font-style: italic;">// build city criteria</span>
   	<span style="color: #000088;">$cityC</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Criteria<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  	<span style="color: #000088;">$cityC</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">add</span><span style="color: #009900;">&#40;</span>CityPeer<span style="color: #339933;">::</span><span style="color: #004000;">STATE_ID</span><span style="color: #339933;">,</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getObject</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getStateId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setWidgets</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
      <span style="color: #0000ff;">'name'</span>   			<span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">new</span> sfWidgetFormInput<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
      <span style="color: #0000ff;">'country_id'</span>		<span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">new</span> sfWidgetFormPropelSelect<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'model'</span><span style="color: #339933;">=&gt;</span><span style="color: #0000ff;">'Country'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'add_empty'</span><span style="color: #339933;">=&gt;</span><span style="color: #0000ff;">'-- Country --'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'order_by'</span><span style="color: #339933;">=&gt;</span>array<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Name'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'asc'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
      <span style="color: #0000ff;">'state_id'</span>		<span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">new</span> sfWidgetFormPropelSelect<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'model'</span><span style="color: #339933;">=&gt;</span><span style="color: #0000ff;">'State'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'add_empty'</span><span style="color: #339933;">=&gt;</span><span style="color: #0000ff;">'-- State/Province --'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'order_by'</span><span style="color: #339933;">=&gt;</span>array<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Name'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'asc'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'criteria'</span><span style="color: #339933;">=&gt;</span><span style="color: #000088;">$stateC</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
      <span style="color: #0000ff;">'city_id'</span>			<span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">new</span> sfWidgetFormPropelSelect<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'model'</span><span style="color: #339933;">=&gt;</span><span style="color: #0000ff;">'City'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'add_empty'</span><span style="color: #339933;">=&gt;</span><span style="color: #0000ff;">'-- City --'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'order_by'</span><span style="color: #339933;">=&gt;</span>array<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Name'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'asc'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'criteria'</span><span style="color: #339933;">=&gt;</span><span style="color: #000088;">$cityC</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
      <span style="color: #0000ff;">'id'</span>				<span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">new</span> sfWidgetFormInputHidden<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setValidators</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
    	<span style="color: #0000ff;">'name'</span>			<span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">new</span> sfValidatorString<span style="color: #009900;">&#40;</span>
    							<span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
    								<span style="color: #0000ff;">'trim'</span>		<span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span>
    								<span style="color: #0000ff;">'required'</span>	<span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span>
    							<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
    								<span style="color: #0000ff;">'required'</span>	<span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'- Please enter name'</span><span style="color: #339933;">,</span>
    							<span style="color: #009900;">&#41;</span>
    					<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    	<span style="color: #0000ff;">'country_id'</span>	<span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">new</span> sfValidatorPropelChoice<span style="color: #009900;">&#40;</span>
    							<span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
    								<span style="color: #0000ff;">'model'</span>		<span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Country'</span><span style="color: #339933;">,</span>
    								<span style="color: #0000ff;">'column'</span>	<span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'id'</span><span style="color: #339933;">,</span>
    							<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
    								<span style="color: #0000ff;">'required'</span>	<span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'- Please choose country'</span><span style="color: #339933;">,</span>
    								<span style="color: #0000ff;">'invalid'</span>	<span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'- Invalid country'</span><span style="color: #339933;">,</span>
    							<span style="color: #009900;">&#41;</span>
    					<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    	<span style="color: #0000ff;">'state_id'</span>		<span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">new</span> sfValidatorPropelChoice<span style="color: #009900;">&#40;</span>
    							<span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
    								<span style="color: #0000ff;">'model'</span>		<span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'State'</span><span style="color: #339933;">,</span>
    								<span style="color: #0000ff;">'column'</span>	<span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'id'</span><span style="color: #339933;">,</span>
    								<span style="color: #0000ff;">'criteria'</span>	<span style="color: #339933;">=&gt;</span> clone <span style="color: #000088;">$stateC</span><span style="color: #339933;">,</span>
    							<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
    								<span style="color: #0000ff;">'required'</span>	<span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'- Please choose state'</span><span style="color: #339933;">,</span>
    								<span style="color: #0000ff;">'invalid'</span>	<span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'- Invalid state'</span><span style="color: #339933;">,</span>
    							<span style="color: #009900;">&#41;</span>
    					<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    	<span style="color: #0000ff;">'city_id'</span>		<span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">new</span> sfValidatorPropelChoice<span style="color: #009900;">&#40;</span>
    							<span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
    								<span style="color: #0000ff;">'model'</span>		<span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'City'</span><span style="color: #339933;">,</span>
    								<span style="color: #0000ff;">'column'</span>	<span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'id'</span><span style="color: #339933;">,</span>
    								<span style="color: #0000ff;">'criteria'</span>	<span style="color: #339933;">=&gt;</span> clone <span style="color: #000088;">$cityC</span><span style="color: #339933;">,</span>
    							<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
    								<span style="color: #0000ff;">'required'</span>	<span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'- Please choose city'</span><span style="color: #339933;">,</span>
    								<span style="color: #0000ff;">'invalid'</span>	<span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'- Invalid city'</span><span style="color: #339933;">,</span>
    							<span style="color: #009900;">&#41;</span>
    					<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    	<span style="color: #0000ff;">'id'</span>			<span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">new</span> sfValidatorNumber<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'required'</span><span style="color: #339933;">=&gt;</span>false<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">widgetSchema</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setLabels</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
		<span style="color: #0000ff;">'name'</span>	<span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Name'</span><span style="color: #339933;">,</span>
	<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">widgetSchema</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setNameFormat</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'user[%s]'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">errorSchema</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> sfValidatorErrorSchema<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">validatorSchema</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getModelName<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
  	<span style="color: #b1b100;">return</span> <span style="color: #0000ff;">'User'</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>This form is not much different from a common form, using sfWidgetFormPropelSelect to show a list of available objects, except by the new option I added, criteria. As can be seen at the top of the code, I build two criterias that are used to filter state and city, based on current selection. This will make the state select only display states belonging to selected country, and cities belonging to selected state. Also, if no country is selected, state and city list will be empty.<br />
Another important step that must be done in order to use sfWidgetFormPropelSelect is to create the magic method __toString to Country, State and City objects. Just add the following code to ALL three classes:</p>
<p>lib/model/Country.class.php, lib/model/State.class.php, lib/model/City.class.php:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __toString<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span></pre></div></div>

<p>The template needs a special attention as well. As will we use AJAX to update the select boxes without reloading the page, we need to split the edit template in two files, the main file and a partial file that will contain the select boxes and the ajax calls:</p>
<p>editSuccess.php:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">&lt;form method=&quot;post&quot; action=&quot;<span style="color: #000000; font-weight: bold;">&lt;?=</span>url_for<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'citypicker/edit?id='</span><span style="color: #339933;">.</span><span style="color: #000088;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getObject</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&quot;&gt;
  <span style="color: #000000; font-weight: bold;">&lt;?=</span><span style="color: #000088;">$form</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;id&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">render</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
  &lt;table&gt;
  	<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$errors</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
    &lt;tr&gt;
    	&lt;td colspan=&quot;2&quot;&gt;
    		&lt;ul&gt;
    			<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$errors</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$error</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
					&lt;li&gt;<span style="color: #000000; font-weight: bold;">&lt;?=</span><span style="color: #000088;">$error</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/li&gt;
				<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endforeach</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
    		&lt;/ul&gt;
    	&lt;/td&gt;
    &lt;/tr&gt;
	<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endif</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
    &lt;tr&gt;
      &lt;th&gt;<span style="color: #000000; font-weight: bold;">&lt;?=</span><span style="color: #000088;">$form</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;name&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">renderLabel</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/th&gt;
      &lt;td&gt;<span style="color: #000000; font-weight: bold;">&lt;?=</span><span style="color: #000088;">$form</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;name&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">render</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Address&lt;/th&gt;
      &lt;td&gt;
        &lt;div id=&quot;address&quot;&gt;
        	<span style="color: #000000; font-weight: bold;">&lt;?=</span>include_partial<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'address_edit'</span><span style="color: #339933;">,</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'form'</span><span style="color: #339933;">=&gt;</span><span style="color: #000088;">$form</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
        &lt;/div&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td colspan=&quot;2&quot;&gt;
        &lt;input type=&quot;submit&quot; name=&quot;submit&quot; value=&quot;save&quot;/&gt;
        <span style="color: #000000; font-weight: bold;">&lt;?=</span>button_to<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'cancel'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'citypicker/index'</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/table&gt;
&lt;/form&gt;</pre></div></div>

<p>_address_edit.php:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span> use_helper<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Javascript'</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?=</span><span style="color: #000088;">$form</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;country_id&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">render</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
	<span style="color: #0000ff;">'onchange'</span>	<span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'$(this.form).request({
						parameters: {refresh: &quot;Y&quot; },
						onComplete: function (r) { $(&quot;address&quot;).update(r.responseText) }
					});'</span>
<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?=</span><span style="color: #000088;">$form</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;state_id&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">render</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
	<span style="color: #0000ff;">'onchange'</span>	<span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'$(this.form).request({
						parameters: {refresh: &quot;Y&quot; },
						onComplete: function (r) { $(&quot;address&quot;).update(r.responseText) }
					});'</span>
<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?=</span><span style="color: #000088;">$form</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;city_id&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">render</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>This code submits the form every time the user changes either country or state boxes. Note that it will append an extra parameter to the form, called refresh, in order to tell the action that it&#8217;s only updating the boxes, and not actually submitting the form. Also, when the call is finished, it will update the #address (div container defined in editSuccess.php template file) element with the response received.</p>
<p>Now, the only piece missing to make this work is the actual edit action, that will handle both form submission and boxes update. </p>
<p>actions.class.php:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> executeEdit<span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
  	<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'id'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000088;">$user</span> <span style="color: #339933;">=</span> UserPeer<span style="color: #339933;">::</span><span style="color: #004000;">retrieveByPK</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;id&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  	<span style="color: #b1b100;">else</span> <span style="color: #000088;">$user</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> User<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  	<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">forward404Unless</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$user</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  	<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">errors</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  	<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isMethod</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'post'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
  	<span style="color: #009900;">&#123;</span>
  		<span style="color: #666666; font-style: italic;">// pre-populate country, state and city in order to filter select boxes</span>
  		<span style="color: #000088;">$data</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'user'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  		<span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setCountryId</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">@</span><span style="color: #000088;">$data</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'country_id'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  		<span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setStateId</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">@</span><span style="color: #000088;">$data</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'state_id'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  		<span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setCityId</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">@</span><span style="color: #000088;">$data</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'city_id'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  		<span style="color: #666666; font-style: italic;">// check validity</span>
  		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCity</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCity</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getStateId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getStateId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setCityId</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getState</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getState</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCountryId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCountryId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setStateId</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCountry</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setCountryId</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">form</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> CPUserForm<span style="color: #009900;">&#40;</span><span style="color: #000088;">$user</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'user'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'refresh'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #0000ff;">&quot;Y&quot;</span><span style="color: #009900;">&#41;</span>
  		<span style="color: #009900;">&#123;</span>
  			<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isValid</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
  			<span style="color: #009900;">&#123;</span>
  				<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">save</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  				<span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">redirect</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'citypicker/index'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  			<span style="color: #009900;">&#125;</span>
&nbsp;
		  	<span style="color: #666666; font-style: italic;">// get errors into array</span>
		  	<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getFormFieldSchema</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getError</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$e</span><span style="color: #009900;">&#41;</span>
		  		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">errors</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$e</span><span style="color: #339933;">;</span>
  		<span style="color: #009900;">&#125;</span>
  		<span style="color: #b1b100;">else</span>
  		<span style="color: #009900;">&#123;</span>
  			<span style="color: #666666; font-style: italic;">// render city/state/country</span>
  			<span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">renderPartial</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'address_edit'</span><span style="color: #339933;">,</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'form'</span><span style="color: #339933;">=&gt;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">form</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  		<span style="color: #009900;">&#125;</span>
  	<span style="color: #009900;">&#125;</span>
  	<span style="color: #b1b100;">else</span> 
  	<span style="color: #009900;">&#123;</span>
  		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">form</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> CPUserForm<span style="color: #009900;">&#40;</span><span style="color: #000088;">$user</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  	<span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span></pre></div></div>

<p>Again, this action is not much different from a common edit action, but there are some extra code to handle the box update. At first, we extract selected country, state and city from the parameters array and populate the user object with these values. This step is needed in order to make the criterias (defined in the form) to work, as it fetches data from the object. Also, we validate these data in order to ensure that selected state belongs to selected country, and that selected city belongs to selected state (well, I guess this can be removed as the criterias will filter it, but I&#8217;ll leave it as I didnt test &#8211; another point to improve). Another change is the check for the refresh parameter. If it&#8217;s set to Y, we skip form validation and just render the _address_edit partial. This partial will be received by the ajax call and will update the form with new select boxes values. Another small detail on this sample is the error handling. After validation, if there&#8217;s any error, I get the list of error messages and create an array with these values, then send it to the template, that in turn will render a unordered list with the messages. I did this because this form has a special design and putting the error messages together with the fields would mess the box design.</p>
<p>Well, that&#8217;s it, now you have the form working. There are some things that can be done in order to improve user experience. Actually experience told me that it MUST be done. One thing is to disable ALL boxes as soon as the user changes it&#8217;s value and only re-enabling after update is finished. Also, you can add an ajax indicator somewhere to tell the user that it&#8217;s still working. If you don&#8217;t do this, it&#8217;s most likely that users will get confused with the boxes (and they WILL, trust me, hehe). </p>
<p>This small tutorial maybe looks a bit confuse, with lots of code with not much explanation, but I hope this can be useful for you. It would be nice to hear feedback from the readers, specially comments about how to improve the form (I&#8217;m not really an symfony expert). </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.barros.ws/2008/10/26/countrystatecity-picker-in-symfony-11/feed/</wfw:commentRss>
		<slash:comments>34</slash:comments>
		</item>
	</channel>
</rss>
