I have a form consisting of 11 elements (input and select tags). The form has form validation that prompts an error message next to field when a user inputs incorrect data. I want to maintain the correct data entered into the fields after the page is refreshed.
For instance, let's say that 10 fields where populated correctly and 1 field incorrectly. When the user presses the submit button, an error message is shown near the field. What I want to do is to keep the 10 correct values selected so the user does no have to start all over again.
For the input elements, this is working fine but for the select elements this is not working. Important is that I am populating the drop down list dynamically with PHP.
Is this possible to do in PHP since I cannot figure out how?
Below is an example of how I am generating a drop down list of a select element.
select name="location">
<?php
include("../includes/db_connect.php");
$sql_loc = "SELECT description FROM location ORDER BY description ASC";
$result_loc = mysqli_query($connection, $sql_loc);
if(mysqli_num_rows($result_loc) > 0){
while($row = mysqli_fetch_assoc($result_loc)){
echo '<option value="' . htmlspecialchars($row['description']) . '">'
. htmlspecialchars($row['description'])
. '</option>';
}
}
?>
</select>
As for the input elements I am achieving this using the below:
<input type="text" name="serial" value="<?php echo $serial;?>">
Try this:
<select name="location">
<?php
include("../includes/db_connect.php");
$sql_loc = "SELECT description FROM location ORDER BY description ASC";
$result_loc = mysqli_query($connection, $sql_loc);
if(mysqli_num_rows($result_loc) > 0){
while($row = mysqli_fetch_assoc($result_loc)){
$selected = "";
if ($row['description'] == $location) {
$selected = " selected";
}
echo '<option value="' . htmlspecialchars($row['description']) . '"' . $selected . '>'
. htmlspecialchars($row['description'])
. '</option>';
}
}
?>
</select>
As outlined in the as duplicate linked question the selected
attribute is to mark the option that has been submitted. The selected
attribute addresses the issue to make the selected value visible.
Additionally your code can benefit from data-binding the select element to the (SQL) data in a modular way.
Let us not care for a moment on the retrieval of the data and just say they come from a Generator:
/**
* @param string $name of the select field
* @param string $value of the select field
* @param Generator $data to use as select field option values
* @return string HTML of the select element
*/
function select($name, $value, Generator $data) {
$buffer = sprintf('<select name="%s">', htmlspecialchars($name));
foreach ($data as $option) {
$buffer .= sprintf(
'<option%s>%s</option>',
$value === $option ? ' selected' : '',
htmlspecialchars($option)
);
}
$buffer .= "</select>\n";
return $buffer;
}
This little function returns the HMTL of a select element with the data from a Generator selecting an existing value (if part of the options).
Combining it with any generator, for example from a data-source, it can be easily put into your forms template script:
<form method="post">
<?= select('location', $_POST['location'] ?? 'default value',
datasource($connection, "SELECT description FROM location ORDER BY description ASC", "description")
) ?>
</form>
So if you've got 10 selects, this can be easily adopted. As the database connection as you know it is passed to the datasource
function, it would be interesting to see what that function actually does. That function is even more simple:
/**
* @param mysqli $mysqli
* @param string $query
* @param string $field from query result to use as option values
* @return Generator
*/
function datasource(mysqli $mysqli, $query, $field) {
$result = $mysqli->query($query);
if ($result) foreach ($result as $row) {
yield $row[$field];
}
}
It queries the query on the database connection (it's a different way of writing as in your code, but it's the same $connection
as in your example) and then iterates over the result (if there is a result). Then yielding each option value. That yield
is a special form of returning from a function creating a Generator which is used in the select
function for output, by having the Generator in the foreach
loop there. Each yielding becomes one iteration of the Generator.
I hope this shows how you can benefit from dividing your code into functions. Values that change should be put into variables. This is easily done by creating functions and using parameters for these values. You sort of extend the language to your own special needs, like creating select elements.
Is this possible to do in PHP since I cannot figure out how?
Yes it is possible to keep the values selected, by using the selected attribute on the option elements.
For instance, the <option>
tag below contains that attribute:
<option value="value2" selected>Value 2</option>
If you care about XHTML validation, use selected="selected"
- refer to this answer for more information.
<option value="value2" selected="selected">Value 2</option>
From the examples section of the MDN documentation for <select>
, the following HTML is listed:
<!-- The second value will be selected initially -->
<select name="select"> <!--Supplement an id here instead of using 'name'-->
<option value="value1">Value 1</option>
<option value="value2" selected>Value 2</option>
<option value="value3">Value 3</option>
</select>
To achieve this with the PHP code, the selected attribute needs to be conditionally added to the option.
First, before the while loop, store the selected location in a variable:
$selectedLocation = '';
if (isset($_POST['location'])) {
//Get selected value from values submitted with form
//use $_GET if form is submitted via GET
$selectedLocation = $_POST['location'];
}
Then in the while loop, set that selected attribute when the matching option is found (i.e. when $selectedLocation == $row['description']
).
while($row = mysqli_fetch_assoc()){
$selected = ''; //default to empty string - not selected
if ($selectedLocation == $row['description']) {
$selected = 'selected';
}
echo '<option value="' . htmlspecialchars($row['description']) . '" '.$selected.'>'
. htmlspecialchars($row['description'])
. '</option>';
}
See a demosntration of this in this phpfiddle.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With