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: http://www.colussigroup.it/index.php/Chiedi-Informazioni (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,
  PRIMARY KEY  (id)
);

For the cities:

CREATE TABLE comuni (
  id mediumint(9) NOT NULL auto_increment,
  comune varchar(100) default NULL,
  provincia char(2) default NULL,
  pid mediumint(9) default NULL,
  PRIMARY KEY  (id)
);

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

I used the integrate extension developed by Bruce Morrison here:

http://pubsvn.ez.no/community/trunk/extension/integrate/

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: http://share.ez.no/learn/ez-publish/how-to-create-ez-publish-forms/(language)/eng-GB.

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_{$node.data_map.provincia.id}" 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>
             {/section}
         </select>

and:

<input type="text" value="" name="ContentObjectAttribute_ezstring_data_text_{$node.data_map.comune.id}" 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: http://share.ez.no/learn/ez-publish/ezjscore-ez-publish-javascript-and-ajax-framework. 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: http://docs.jquery.com/Plugins/autocomplete.

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).

<?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;
        var_dump($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):

[ExtensionSettings]
ActiveExtensions[]=citycomplete

For further information on HOWTO with extensions, read: http://share.ez.no/learn/ez-publish/an-introduction-to-developing-ez-publish-extensions.

Step 5: Write the Javascript

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

$(document).ready(function(){

    $("#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.

Ciao!

eZ debug

Timing: Jan 17 2025 22:43:35
Script start
Timing: Jan 17 2025 22:43:35
Module start 'content'
Timing: Jan 17 2025 22:43:35
Module end 'content'
Timing: Jan 17 2025 22:43:35
Script end

Main resources:

Total runtime0.2242 sec
Peak memory usage6,144.0000 KB
Database Queries185

Timing points:

CheckpointStart (sec)Duration (sec)Memory at start (KB)Memory used (KB)
Script start 0.00000.0068 587.8125180.8359
Module start 'content' 0.00680.0912 768.6484417.7813
Module end 'content' 0.09800.1262 1,186.4297412.6172
Script end 0.2242  1,599.0469 

Time accumulators:

 Accumulator Duration (sec) Duration (%) Count Average (sec)
Ini load
Load cache0.00411.8478210.0002
Check MTime0.00140.6461210.0001
Mysql Total
Database connection0.00070.317910.0007
Mysqli_queries0.142063.33631850.0008
Looping result0.00180.81331830.0000
Template Total0.191485.420.0957
Template load0.00220.980220.0011
Template processing0.189284.366820.0946
Template load and register function0.00020.085610.0002
states
state_id_array0.00150.686810.0015
state_identifier_array0.00261.165220.0013
Override
Cache load0.00180.8232510.0000
Sytem overhead
Fetch class attribute name0.00210.926330.0007
Fetch class attribute can translate value0.00070.316610.0007
class_abstraction
Instantiating content class attribute0.00000.003530.0000
XML
Image XML parsing0.00020.108810.0002
General
dbfile0.00311.3749220.0001
String conversion0.00000.004530.0000
Note: percentages do not add up to 100% because some accumulators overlap

CSS/JS files loaded with "ezjscPacker" during request:

CacheTypePacklevelSourceFiles
CSS0extension/community/design/community/stylesheets/ext/jquery.autocomplete.css
extension/community_design/design/suncana/stylesheets/scrollbars.css
extension/community_design/design/suncana/stylesheets/tabs.css
extension/community_design/design/suncana/stylesheets/roadmap.css
extension/community_design/design/suncana/stylesheets/content.css
extension/community_design/design/suncana/stylesheets/star-rating.css
extension/community_design/design/suncana/stylesheets/syntax_and_custom_tags.css
extension/community_design/design/suncana/stylesheets/buttons.css
extension/community_design/design/suncana/stylesheets/tweetbox.css
extension/community_design/design/suncana/stylesheets/jquery.fancybox-1.3.4.css
extension/bcsmoothgallery/design/standard/stylesheets/magnific-popup.css
extension/sevenx/design/simple/stylesheets/star_rating.css
extension/sevenx/design/simple/stylesheets/libs/fontawesome/css/all.min.css
extension/sevenx/design/simple/stylesheets/main.v02.css
extension/sevenx/design/simple/stylesheets/main.v02.res.css
JS0extension/ezjscore/design/standard/lib/yui/3.17.2/build/yui/yui-min.js
extension/ezjscore/design/standard/javascript/jquery-3.7.0.min.js
extension/community_design/design/suncana/javascript/jquery.ui.core.min.js
extension/community_design/design/suncana/javascript/jquery.ui.widget.min.js
extension/community_design/design/suncana/javascript/jquery.easing.1.3.js
extension/community_design/design/suncana/javascript/jquery.ui.tabs.js
extension/community_design/design/suncana/javascript/jquery.hoverIntent.min.js
extension/community_design/design/suncana/javascript/jquery.popmenu.js
extension/community_design/design/suncana/javascript/jScrollPane.js
extension/community_design/design/suncana/javascript/jquery.mousewheel.js
extension/community_design/design/suncana/javascript/jquery.cycle.all.js
extension/sevenx/design/simple/javascript/jquery.scrollTo.js
extension/community_design/design/suncana/javascript/jquery.cookie.js
extension/community_design/design/suncana/javascript/ezstarrating_jquery.js
extension/community_design/design/suncana/javascript/jquery.initboxes.js
extension/community_design/design/suncana/javascript/app.js
extension/community_design/design/suncana/javascript/twitterwidget.js
extension/community_design/design/suncana/javascript/community.js
extension/community_design/design/suncana/javascript/roadmap.js
extension/community_design/design/suncana/javascript/ez.js
extension/community_design/design/suncana/javascript/ezshareevents.js
extension/sevenx/design/simple/javascript/main.js

Templates used to render the page:

UsageRequested templateTemplateTemplate loadedEditOverride
1node/view/full.tplblog_entry/full.tplextension/community_design/design/suncana/override/templates/blog_entry/full.tplEdit templateOverride template
2content/datatype/view/ezxmltext.tpl<No override>extension/community_design/design/suncana/templates/content/datatype/view/ezxmltext.tplEdit templateOverride template
15content/datatype/view/ezxmltags/paragraph.tpl<No override>extension/ezwebin/design/ezwebin/templates/content/datatype/view/ezxmltags/paragraph.tplEdit templateOverride template
7content/datatype/view/ezxmltags/strong.tpl<No override>design/standard/templates/content/datatype/view/ezxmltags/strong.tplEdit templateOverride template
7content/datatype/view/ezxmltags/literal.tpl<No override>extension/community/design/standard/templates/content/datatype/view/ezxmltags/literal.tplEdit templateOverride template
2content/datatype/view/ezxmltags/emphasize.tpl<No override>design/standard/templates/content/datatype/view/ezxmltags/emphasize.tplEdit templateOverride template
1content/datatype/view/ezkeyword.tpl<No override>extension/community_design/design/suncana/templates/content/datatype/view/ezkeyword.tplEdit templateOverride template
1pagelayout.tpl<No override>extension/sevenx/design/simple/templates/pagelayout.tplEdit templateOverride template
 Number of times templates used: 36
 Number of unique templates used: 8

Time used to render debug report: 0.0002 secs