In the users table at my company’s website there are fields for company, division, region, and location. Since each level of the company organization affects all the lower categories I have to filter out the invalid choices when a higher level choice is selected.
I’ve implemented this on some forms that I’ve created manually on the site but not in any forms that I haven’t heavily modified from the stock symfony creation. I started googling around to find a solution but could not find a simple explanation of how to do it. I expected to find at least some information in one of symfony’s otherwise excellent tutorials, but alas, no.
I had a minor epiphany and went digging through the forms API that symfony provides and realized that I should easily be able to do this through the sfWidgetFormPropelChoice method. The second parameter passed is the html attributes for the form field. I thought I had seen a form post here that said that I could add javascript code to the html attributes and not have it get converted into html entities.
I tried throwing a simple alert() inside the onchange attribute for my company box and wham! it worked! So simple. Code below:
new sfWidgetFormPropelChoice( array( 'model' => 'Company', 'add_empty' => true ), array( 'onchange' => "filterBy('company', 'division', this.value, 'sf_guard_user_user_division_id');" . "filterBy('company', 'region', this.value, 'sf_guard_user_user_region_id');" . "filterBy('company', 'location', this.value, 'sf_guard_user_user_location_id');" ) )
Till Next Time
Tags: forms, javascript, onchange, php, sfWidget, symfony, widgets
Hi,
I need this solution. Where is your filterBy() function? Can i get it?
I’m stuck on that problem.
Thanks
@Suborno
here’s the js that I use, it’s not beautiful, but it works:
// handles overall function control
function filterBy(filter_type, result_type, filter_value, field, preshot, select_option)
{
try
{
httpRequest = createFinalHttpRequest();
if(httpRequest != null)
{
/*
* the two items commented out below are what need to be uncommented if you want
* asynchronous transfer.
* A bug exists in the select box filtering when you trigger this event more than
* once on a single event
*
* (i.e.- New Location page, when user selects the Company, Division and Region
* are both automatically populated with appropriate options)
*
*/
var location = ‘/activity/filter?filter_type=’ + filter_type + ‘&result_type=’ + result_type + ‘&filter_value=’ + filter_value;
httpRequest.open(“GET”, location, false);
httpRequest.send(null);
if(httpRequest.readyState == 4)
{
if(httpRequest.status == 200)
{
var response_header = httpRequest.getResponseHeader(“Content-Type”);
if(response_header.indexOf(“text/xml”) != -1 || response_header.indexOf(“application/xml”) != -1)
{
var xml = httpRequest.responseXML;
if(xml)
var results = parseFilterResults(xml, result_type);
if(!results)
alert(‘There has been an error filtering the results’);
else
{
if(select_option)
filterBox(field, results, select_option);
else
filterBox(field, results);
}
}
else
alert(‘Content is NOT xml;\nContent is: ‘ + httpRequest.getResponseHeader(“Content-Type”));
}
}
}
else
alert(“The http request is null!”);
}
catch(err)
{
alert(“There was an error filtering the ” + result_type + “: ” + err);
return false;
}
return true;
}
// creates the actual xml request to server
function createFinalHttpRequest()
{
var xmlhttp;
if (window.XMLHttpRequest)
{
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
}
else
{
// code for IE6, IE5
try
{
xmlhttp = new ActiveXObject(“Msxml2.XMLHTTP”);
}
catch(err)
{
try
{
xmlhttp = new ActiveXObject(“Microsoft.XMLHTTP”);
}
catch(er)
{
xmlhttp = null;
}
}
}
return xmlhttp;
}
// parses the returned xml and creates an array of the values
{
{
{
{
{
function parseFilterResults(xml, type)
{
try
{
var results = new Array();
switch(type)
{
case ‘division’:
var divs = xml.getElementsByTagName(type);
var ids = xml.getElementsByTagName(‘id’);
var names = xml.getElementsByTagName(‘name’);
for(var i=0;i
var id = ids[i].childNodes[0].nodeValue;
var name = names[i].childNodes[0].nodeValue;
results.push(new Array(id, name));
}
break;
case 'region':
var regs = xml.getElementsByTagName(type);
var ids = xml.getElementsByTagName('id');
var names = xml.getElementsByTagName('name');
for(var i=0;i
var id = ids[i].childNodes[0].nodeValue;
var name = names[i].childNodes[0].nodeValue;
results.push(new Array(id, name));
}
break;
case 'location':
var locs = xml.getElementsByTagName(type);
var ids = xml.getElementsByTagName('id');
var names = xml.getElementsByTagName('name');
for(var i=0;i
var id = ids[i].childNodes[0].nodeValue;
try
{
var name = names[i].childNodes[0].nodeValue;
}
catch(ee)
{
var name = "";
}
results.push(new Array(id, name));
}
break;
case 'seismo':
var seismos = xml.getElementsByTagName(type);
var ids = xml.getElementsByTagName('id');
var names = xml.getElementsByTagName('name');
var lats = xml.getElementsByTagName('lat');
var longs = xml.getElementsByTagName('long');
for(var i=0;i
var id = ids[i].childNodes[0].nodeValue;
var name = names[i].childNodes[0].nodeValue;
try
{
var lat = lats[i].childNodes[0].nodeValue;
var long = longs[i].childNodes[0].nodeValue;
}
catch(e)
{
var lat = "";
var long = "";
}
results.push(new Array(id, name, lat, long));
}
break;
case 'activity':
var activities = xml.getElementsByTagName(type);
var ids = xml.getElementsByTagName('id');
var shot_numbers = xml.getElementsByTagName('shot_number');
for(var i=0;i
var id = ids[i].childNodes[0].nodeValue;
try
{
var shot_number = shot_numbers[i].childNodes[0].nodeValue;
}
catch(ee)
{
var shot_number = "";
}
results.push(new Array(id, shot_number));
}
default: // company
break;
}
}
catch(err)
{
alert("There was an error parsing the results: " + err);
return false;
}
return results;
}
// this removes all the options in the given box and adds all the new
addSelectOption(updated_field, options[i][0], options[i][1]);
// options in the options array
function filterBox(field, options, select_option)
{
try
{
var updated_field = document.getElementById(field);
removeAllOptions(updated_field, false);
if(select_option)
addSelectOption(updated_field, "", "Select an Option");
for(var i=0;i
}
catch(err)
{
alert("There has been an erroring filtering the dropdown box: " + err);
return false;
}
return true;
}
// removes all options from a select box with the option
// to add a single 'blank' value option back
function removeAllOptions(sel_box, keep_blank)
{
try
{
for(var i=sel_box.length-1;i>=0;i–)
sel_box.remove(i);
if(keep_blank)
addSelectOption(sel_box, “”, “Select an Option”);
}
catch(err)
{
alert(“There has been an error removing options: ” + err);
return false;
}
return true;
}
// adds an option to a select box
function addSelectOption(field, value, text)
{
try
{
var opt = document.createElement(“option”);
opt.text = text;
opt.value = value;
field.options.add(opt);
}
catch(err)
{
alert(“There was an error adding an option: ” + err);
return false;
}
return true;
}