Blogs / Henrik Gren / Implementing Province => City dependency

Implementing Province => City dependency

Tuesday 18 January 2011 8:39:55 am

  • Currently 5 out of 5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

By : Henrik Gren

Hi everyone!

Since I notice that there are quite some posts on this topic, I thought I should share with you how I implemented a form where one field depends on another. I will use the classic example where the user selects a province and then is limited in his choice of choosing a city only to those cities that actually exist in that province.

The final result can be seen here: (the fields are provincia and comune).

Step1: Create the DB Tables

For the provinces:

CREATE TABLE province (
  id mediumint(9) NOT NULL,
  `name` char(2) default NULL,

For the cities:

  id mediumint(9) NOT NULL auto_increment,
  comune varchar(100) default NULL,
  provincia char(2) default NULL,
  pid mediumint(9) default NULL,

Step 2: Create a custom data type for the province combo box

I used the integrate extension developed by Bruce Morrison here:

Of course you can develop your own data type, but since Bruce did a really nice job here I recommend you use it.

Check the README file for installation instructions.

Step 3: Create the form

For those who are not familiar with the creation of eZ Publish forms, here is the tutorial:

The two fields of the form that interest us were created in this way:

Provincia [External Option] - Table: Province - Index Column: id - Name Column: name

Comune [Text line] - Default Value: Empty

In the chiedi_informazioni.tpl, the code for the two fields is:

<select class="formelement" id="prov" name="ContentObjectAttribute_data_int_{$}" style="width: 155px;">
             <option value="">Seleziona la provincia</option>
             {section loop=$node.data_map.provincia.content.options}
                <option value="{$item.val|wash(xhtml)}"{if eq($value, $item.val)} selected="selected"{/if}>{$item.label|wash(xhtml)}</option>


<input type="text" value="" name="ContentObjectAttribute_ezstring_data_text_{$}" id="city" class="formelement" style="width: 150px;" />

At this point we have a fully functioning form, but we are missing the last bit (the purpose of this post): The dependency. We accomplish this in two steps: Creating an ezjscore extension and adding a little bit of jQuery to our .tpl.

Step 4: Create the extension

There is the ezjscore tutorial here: I spent a few days before I could connect all the pieces. Probably I was lacking some jQuery skills and for this particular case you would find that information here:

If you don't have ezjscore already, as part of ezflow or ezwebin you should install it first.

This is the code that you should put in your /extension/yourextension/classes/extensionfunction.php (in my case it is /extension/citycomplete/classes/completecityfuncion.php).


class completeCityFunction extends ezjscServerFunctions
    public static function searchCities($args)
        $query = '';
        $db =& eZDB::instance();

        $http = eZHTTPTool::instance();
        $query="select distinct(comune) from comuni where comune like '".trim($http->getVariable( 'q' ))."%' and pid ='".$http->getVariable( 'province' )."'";

        $result = $db->arrayQuery($query);

        return $result;


I made this extension available through the admin interface and I put it in the site.ini.append.php in the /settings/override directory (you could choose any other of a number of options depending on your needs):


For further information on HOWTO with extensions, read:

Step 5: Write the Javascript

Simply, here is the code. If you stray from it, you will find trouble.


    $("#city").autocomplete('/index.php/ezjscore/call/citycomplete::searchCities', {
        dataType: "json",
        mustMatch: true,
        minChars: 1,
        parse: function(data) {
            return $.map(data.content, function(row) {
                return {
                    data: row.comune,
                    value: row.comune,
                    result: row.comune
        formatItem: function(item) {
            return item;
        extraParams: {
            province: function() { return $("#prov").val();}

Note: If you prefer, you could substitute the combo-box with a text box. In that case you would not need Bruce's datatype anymore, you would have to add a new extension, similar to the citycomplete extension, and you would need to modify you SQL a little.