Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Dependent Select Boxes

Status
Not open for further replies.

PCHomepage

Programmer
Feb 24, 2009
609
1
16
US
I created a relatively simply function that gets its input from another select box. There are actualy six of each in two rows making twelve select boxes all together that are used for building up a dynamic query but I'm have a little trouble figuring out the logic. They are working togeother but not as needed.

In the blue lines below, I am trying to retrieve the values being submitted by the previous select box so that I can have the next one bring up only valid results but when I select one, no values appear in any.

In the red area, I am trying to create an array of values from multiple choices but the choices are not numeric and I can't seen to get then enquoted even though I have a function for doing so. When I try, it gives an array of all values including the empty ones. It is the array that is to be used in the next select box to know what to choose but as it exists only in the previous select box, I am not sure how to pass it on from select box to select box AND accumulate the array values from one to the next so that each successive select box fetches only valid entries. Only the Value2 and forward select boxes need the information

Also, the boxes need to auto-submit AND allow multiple choices but it seems to remember only one choice. Any ideas?

The function input variables are:

[bold]$NameVal[/bold] is the name of the select box, ie: Value1, Value2 etc.
[bold]$DefaultVal[/bold] is what shows at the top of the list box as a label, ie "Value 1", "Value 2" etc.
[bold]$SelectVal[/bold] is the value coming into it from the select box above it that tells it what data to select

Code:
function Value($NameVal, $DefaultVal, $SelectVal, $mysqli) {
	global $Selected;
	global $Where;

	[COLOR=blue]// Create variables from posts
	$Value1 = ($NameVal != "Value1") ? $_POST['Value1'][0]: $Value1 = "";	
	$Value2 = ($NameVal != "Value2") ? $_POST['Value2'][0]: $Value2 = "";
	$Value3 = ($NameVal != "Value3") ? $_POST['Value3'][0]: $Value3 = "";
	$Value4 = ($NameVal != "Value4") ? $_POST['Value4'][0]: $Value4 = "";
	$Value5 = ($NameVal != "Value5") ? $_POST['Value5'][0]: $Value5 = "";
	$Value6 = ($NameVal != "Value6") ? $_POST['Value6'][0]: $Value6 = "";
	
	$Values = array($Value1, $Value2, $Value3, $Value4, $Value5, $Value6);[/color]

	[COLOR=red]// Build array of values already selected
	if (is_array($Values) && count(array_filter($Values)) > 0):
		$Value = array_filter($Values);
		$AndID = " (";		
		$AndID .= implode(",", $Value);
		$AndID .= ") ";
	endif;[/color]
		
	if ($SelectVal) $Where = " WHERE KeyID = ".$SelectVal;
	if (!$SelectVal) $Where = " WHERE KeyID = IS NULL"; // Keeps select box depopulated until needed
	if ($AndID) $Where .= " AND QEValue IN ".$AndID;
	
	$Query = " SELECT DISTINCT Value, ID FROM keys ".$Where." GROUP BY Value ORDER BY Value";
	
	$Multiple = " multiple=\"multiple\"";
	$NumRows = " size=\"5\"";
	$AddRow = "<option value=\"\"></option>\n";
	$OnChange = " onchange='this.form.submit()'";

	$Output = "<select name=\"".$NameVal."[]\" id=\"".$NameVal."[]\" class=\"SelectBox\"".$OnChange.$Multiple.$NumRows.">\n";
	$Output .= "<option value=\"\">".$DefaultVal."</option>\n";
	if ($Where):
		if ($result = $mysqli->query($Query)):
			$i = 0;
			while ($row = $result->fetch_row()):
				$Selected = ($row[0] == $_POST[$NameVal][0]) ? $Selected = " SELECTED" : $Selected = "";
				$Output .= "<option value=\"".$row[0]."\"".$Selected.">".$row[0]."</option>\n";
				$i++;
			endwhile;
			$result->close();
		endif;
	endif;
	$Output .= "</select>";
	echo $Output;
}
 
sorry PCHomePage - I am approaching the problem differently to you and am already about 70% through a UI + back end solution, interacting via javascript (so the filtered files are automatically updated in a grid). Hence my doggedness in getting to the bottom of the business solution.

I don't like the way you bundle everything into a parameterised function as I fear this oversimplification will create headaches when you try to deal with all the potential parameters; if encapsulation is necessary I prefer it to be in a clearly defined class but in this case I don't see encapsulation as particularly necessary. that does not make you wrong, just the approach is a bit alien and so I am struggling with it.

on your reported issue it sounds like your naming convention in the form is skewed, imo. you can fudge the issue by adding a [0] to the end of $inValues in the implode but this would not be a great solution if more than one sub-select is populated.

In the short term I will finish up a solution based on the the three permissible values in the first select box.
 
Since I'm in the last week of the contract, I don't really have the time to start over but I appreciate your help and advice as always. Also, the person who will be managing this after I've gone knows C well but not PHP so I tried to keep it as simple and straightforward as possible by blocking everything out to basic functions.

The one hurdle that has had me bogged down is the "SELECTED" value for multiple-selects on the second Values form and I haven't even gotten to a couple other similar but simpler forms! This one is working after a fashion but only the last value is being remembered so until that's fixed, I cannot even try to finish up the queries. Here is what I have that is partially working:

Code:
if ($Where):
	if ($result = $mysqli->query($Query)):
		$i = 0;
		while ($row = $result->fetch_row()):
			foreach ($row as $key):
				$Selected = ($row[0] == $_POST[$NameValue][$key]) ? " SELECTED" : "";
			endforeach;							
			$Output .= "<option value=\"".$row[0]."\"".$Selected.">".substr(basename($row[0], '.csv'),0,50)."</option>\n";
			$i++;
		endwhile;
		$result->close();
	endif;
endif;

I also need to revisit the query in the Name select box. When it receives a value from the Value select box, it gives only a single result so I'll have to run some tests through phpmyadmin to figure out what it really needs. This is a funky database with all the keywords in one column and all the values next to them in another, repeated over and over but that's the way it is so I have little choice but to make do. For other areas of teh site I created teh tables but this portion was inherited from an existing schema. Anyway, here is what I've worked out and it is functional aside from the need to come up with a different query.

Code:
	if (is_array($InNames) && count($InNames) > 0):
		$AndID = " (";		
		$AndID .= implode(",", $InNames);
		$AndID .= ") ";
		$Where .= " AND KeyID NOT IN ".$AndID;
	endif;	

	// Build variable of values already selected, select only relevant entries
	if (is_array($InValues) && count($InValues) > 0):
		// Custom function to convert multidimensional array to single dimensional
		$InValues = array_values_recursive($InValues);
		$AndValue = " (";		
		$AndValue .= implode(",", array_map('enquote', $InValues));
		$AndValue .= ") ";
		$Where .= " AND QEValue IN ".$AndValue;		
	endif;

	$Query = " SELECT DISTINCT KeyName, KeyID 
				FROM dcs_keys ".$Where." 
				GROUP BY KeyName 
				ORDER BY KeyName";
 
The query that I posted a while ago is okay but what I realized is that after the first Name and Value selection have been made, the query needs to change totally since otherwise the Name selectors are all empty. In other words, running a basic query manually on a couple pieces of data as in the rough example below brings up a given number of rows (58 in this case) but the rows, of course, do not include any other keyword rows which are for the same part. I am not sure how I can pull up the other information since the query specifically tells it not to!

There is another table, dcs_keysvals, which has the same data in a horizontal format with each column having the same name as the Name select box choices but I am not sure how to use it for this purpose.

Code:
SELECT * 
FROM dcs_keys 
WHERE QEValue IN ('C1BA','C1CA')
 
I reverted the query back to what it was before the original post where it was selecting from a dcs_keywords table but this time I joined it back to the dcs_keys table. I'm not sure, though, if it gained anything and it's impossible to tell as long as the multi-Value form loses its selections. Anyway, here is the query now:

Code:
$Query = "SELECT DISTINCT k.KeywordName AS KeyName, k.ID AS KeyID 
		FROM dcs_keywords k, dcs_keys j  ".$Where;

The whole query with all the filters and after a Value selection looks something like this:

Code:
SELECT DISTINCT k.KeywordName AS KeyName, k.ID AS KeyID 
FROM dcs_keywords k, dcs_keys j 
WHERE k.KeywordName IS NOT NULL 
AND k.KeywordName NOT LIKE 'color%' 
AND k.KeywordName NOT LIKE 'CCM%' 
AND k.KeywordName NOT LIKE 'SNR%' 
AND k.KeywordName NOT LIKE 'NG%' 
AND k.KeywordName NOT LIKE 'Max%' 
AND k.KeywordName NOT LIKE 'Mean%' 
AND k.KeywordName NOT LIKE 'peak%' 
AND k.ID NOT IN (109,39) 
AND j.QEValue IN ('6532589','6534749','6534759')

Of course, I made several other Value selections too but they've disappeared without the multi-Value SELECTED working so getting that fixed is my most immediate goal. I think the upper Name selector is working well enough for now.
 
@PCHomepage

without the business rules and your table structures it's very difficult to follow what you are doing.

For example,

1. if I have selected datatype from the first drop down what column of what table is queried (in the where clause) in order to obtain the VALUES that need to go into the sub-select (and what values are required)?

2. ditto selecting 'date'

3. ditto selecting chip

Next, assuming that we have lots of filters pre-set

4. what table is queried to obtain the list of filtered files and for each 'type' chosen in the first select, what is the column of the filtered table that is queried.

This will help with the understanding of the problem.
 
Thank you. As stated earlier, I've moved past the first form and onto the second one but can go nowhere until I get the multi-select Value form to remember the selections. I seem to be able to get it to remember all, one or none but not the specific ones selected! Here is the function again as it's been changed since the last time I posted it.

Code:
// Select box specific to QE component VALUEs
function QEValue($NameValue, $DefaultValue, $NameIn, $ValuesIn, $mysqli) {

	$AndID = (is_array($ValuesIn) && count($ValuesIn)) ? " AND QEValue IN (".implode(",", array_map('enquote', array_filter($ValuesIn))).")": "";

	$Where = ($NameIn)  ? " WHERE KeyID = ".$NameIn: " WHERE KeyID = IS NOT NULL";
	$Where .= (is_array($AndID)) ? $AndID: "";
	
	$Query = " SELECT DISTINCT QEValue AS Value FROM dcs_keys ".$Where." GROUP BY QEValue ORDER BY QEValue";
	
	$Multiple = " multiple=\"multiple\"";
	$NumRows = " size=\"5\"";
	$AddRow = "<option value=\"\"></option>\n";
	$OnChange = " onblur='this.form.submit()'";

	$Output = "<select name=\"".$NameValue."[]\" id=\"".$NameValue."[]\" class=\"SelectBox\"".$OnChange.$Multiple.$NumRows.">\n";
	$Output .= "<option value=\"\">".$DefaultValue."</option>\n";
	if ($Where):
		if ($result = $mysqli->query($Query)):
			$i = 0;
			while ($row = $result->fetch_row()):
					$RowVal = $row[0];
					[COLOR=red]$Selected = ($key[0] == $_POST[$NameValue]) ? " SELECTED" : "";[/color]
					$Output .= "<option value=\"".$row[0]."\"".$Selected.">".substr(basename($row[0], '.csv'),0,50)."</option>\n";
				$i++;
			endwhile;
			$result->close();
		endif;
	endif;
	$Output .= "</select>";
	echo $Output;
}
 
I don't see how we can help without knowing

1. what the form looks like (the names of the controls)
2. what the shape of each parameter being passed into the function might be.

how about simplifying this? post only the form that you are using and the receiving code. don't put anything in a function, leave it all in the global scope. once you have that working, you can encapsulate in a function.

be sure to provide us with the business rules that are necessary to make sense of the form and receiving code.
 
The bit highlighted in red in the last post is all I need help with right now. The form was posted abode; the output arrays were also posted. I just can't seen to get the value from the form to be able to apply the SELECTED because I am unsure of $_POST[$NameValue] which should be the names of the form selectors, ie. $_POST['Value1']; $_POST['Value2'] etc. Since it is an array, it will never equal $row[0] (I accidentally had $key[0] above, which was wrong.) If I use this, it remembers a single selection:

Code:
if ($Where):
	if ($result = $mysqli->query($Query)):
		$i = 0;
		while ($row = $result->fetch_row()):
			[COLOR=red]$Value = $_POST[$NameValue];
			$Selected = ($row[0] == $Value[0]) ? " SELECTED" : "";
			$Output .= "<option value=\"".$row[0]."\"".$Selected.">".substr(basename($row[0], '.csv'),0,50)."</option>\n";[/color]
			$i++;
		endwhile;
		$result->close();
	endif;
endif;
 
the correct attribute=value paid to show an option as selected is
Code:
selected="selected"

You are only outputting half that.

I cannot find a place in the post where you have shown the shape of the $_POST[$NameValue] array. assuming it is the second anonymous array above I suppose it derives from the fact that you are calling the sub-selects "value1[]". Can you explain why you have put square brackets after the name? removing them seems a good start. however even with them in I don't quite see how you have so many null array keys unless you are not showing a fair representation of your html form.
 
jpadie said:
Can you explain why you have put square brackets after the name?

Because they are multiple selects, and its the only way to get them to be arrays in PHP? At least that was my understanding.

I think the only issue here, is the fact that since the selects can have multiple values selected they can be arrays, and such needs to be stepped through, or checked in some way.

Personally I'd check for the existence of the current value in the POSTED value array. Rather than simply checking the first position of the array for a match, as that would only every match a single value from the query.

Code:
[COLOR=#009900]$Selected[/color] [COLOR=#990000]=[/color] [COLOR=#990000]([/color][b][COLOR=#000000]in_array[/color][/b][COLOR=#990000]([/color][COLOR=#009900]$row[/color][COLOR=#990000][[/color][COLOR=#993399]0[/color][COLOR=#990000]],[/color][COLOR=#009900]$Value[/color][COLOR=#990000]))[/color] [COLOR=#990000]?[/color] [COLOR=#FF0000]"selected='selected'"[/color] [COLOR=#990000]:[/color] [COLOR=#FF0000]""[/color][COLOR=#990000];[/color]

----------------------------------
Phil AKA Vacunita
----------------------------------
Ignorance is not necessarily Bliss, case in point:
Unknown has caused an Unknown Error on Unknown and must be shutdown to prevent damage to Unknown.

Web & Tech
 
I agree that normally a multiple select is named as an array. silly me.

However look at the shape of the array that the OP posts
Code:
Array
(
    [0] => Array
        (
            [0] => C1BA
            [1] => C1CA
            [2] => K46B
        )

    [1] => 
    [2] => 
    [3] => 
    [4] => 
    [5] => 
)

this is not consistent with a single multiple select.
 
Thank you! Perfect! That was exactly what I needed and, after adding a check to be sure it is array (because it isn't until the Names selector has been submitted), it seems to work just as it should. Now I can move on to built the WHEREs for the other Value selectors, which should be reasonably easy.

Code:
$Selected = ([COLOR=red]is_array($Value) &&[/color] in_array($row[0],$Value)) ? "selected='selected'" : "";

As for the square brackets, as I understand it, since it it a multiple select it requires them. Also the code to which this submits to bring up the list of files expects an array and without the square brackets, it crashes. Because other pforms of the site use the same code, it was easier and faster to have the square brackets here too rather than trying to rebuild everything else.

As for "selected='selected'" vs. "SELECTED", it seems to work either way but I've not looked up the standard to see what it should be. I've always used just "SELECTED" without any problems and it it seems to be accepted by all browsers that I have available.
 
Yes, I find that structure rather strange. Technically speaking there's no way a dropdown would submit an array with more than one dimension.
Can you show us what you are doing to the posted arrays before passing them to the function?


----------------------------------
Phil AKA Vacunita
----------------------------------
Ignorance is not necessarily Bliss, case in point:
Unknown has caused an Unknown Error on Unknown and must be shutdown to prevent damage to Unknown.

Web & Tech
 
I can't copy and paste from the Web server to this PC so this might not be the most up-to-date version but the functions for creating the two rows of selector boxes are being called like this:

Code:
// Get POSTED values from form NAME select boxes
$Name1 = (isset($_POST['Name1'])) ? $_POST['Name1']: "";	
$Name2 = (isset($_POST['Name2'])) ? $_POST['Name2']: "";
$Name3 = (isset($_POST['Name3'])) ? $_POST['Name3']: "";
$Name4 = (isset($_POST['Name4'])) ? $_POST['Name4']: "";
$Name5 = (isset($_POST['Name5'])) ? $_POST['Name5']: "";
$Name6 = (isset($_POST['Name6'])) ? $_POST['Name6']: "";

// Create an array of NAME selectors being sent
$InNames = array($Name1,$Name2,$Name3,$Name4,$Name5,$Name6);

// Get POSTED values from form VALUE select boxes	
$Value1 = (isset($_POST['Value1'])) ? $_POST['Value1']: "";	
$Value2 = (isset($_POST['Value2'])) ? $_POST['Value2']: "";
$Value3 = (isset($_POST['Value3'])) ? $_POST['Value3']: "";
$Value4 = (isset($_POST['Value4'])) ? $_POST['Value4']: "";
$Value5 = (isset($_POST['Value5'])) ? $_POST['Value5']: "";
$Value6 = (isset($_POST['Value6'])) ? $_POST['Value6']: "";

// Create an array of VALUE selectors being sent
$InValues = array($Value1,$Value2,$Value3,$Value4,$Value5,$Value6);

echo "<p>Select Keywords:<br>\n";
QEKeyword('Name1', 'Name 1', $InNames, $InValues, $mysqli);
QEKeyword('Name2', 'Name 2', $InNames, $InValues, $mysqli);	
QEKeyword('Name3', 'Name 3', $InNames, $InValues, $mysqli);
QEKeyword('Name4', 'Name 4', $InNames, $InValues, $mysqli);
QEKeyword('Name5', 'Name 5', $InNames, $InValues, $mysqli);
QEKeyword('Name6', 'Name 6', $InNames, $InValues, $mysqli);			

echo "<p>Select Values:<br>\n";
QEValue('Value1', 'Value 1', $Name1, $InValues, $mysqli);
QEValue('Value2', 'Value 2', $Name2, $InValues, $mysqli);	
QEValue('Value3', 'Value 3', $Name3, $InValues, $mysqli);
QEValue('Value4', 'Value 4', $Name4, $InValues, $mysqli);
QEValue('Value5', 'Value 5', $Name5, $InValues, $mysqli);
QEValue('Value6', 'Value 6', $Name6, $InValues, $mysqli);
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top