Cascading dropdowns that then lead to datatable

example is here: Install Check

I have the page working through form reloading on submit, but I am sure there is probably a better way to do it with datatables/ajax and wonder if you could advise?

So there are 3 drop downs, you choose location, then it reveals room drop down, you choose room and then it reveals the datatable filtered to those two dropdowns, and then has an optional drop down to filter more if required.

My current code is using SQL to pull the data then transferring it to the datatable, I have an editor licence, but not sure that helps here.

There is an install function that essentially changes the status when they click it, I know I can get Datatables to do that and will get that working when I get the load improved.

Here below code is working fine but when you choose location - the whole page reloads / refereshed and display second dropdown for room … again when you choose room - the whole page reloads/ refereshed and reveals the datatable filtered to those two dropdowns. My question is … Is it possible that instead of refresh whole page only data/ content reflect ? Is there anything that I can add or remove from below code?

My Code:

<?php

//SESSION START

if(!isset($_SESSION)) {

  session_start();

}

$actual_link = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";

if (strpos($actual_link, 'test.assettrack')) {

  $path ="https://test.assettrack.cx";

} else {

  $path = "https://assettrack.cx";

}

//PERMISSIONS (REQUIRED IN INCLUDE)

$public = 1; // 0 = Have to be logged in, 1 = Anyone can view.

$permission = 15; //10 = User, 20 = Tester, 30 = Admin, 40 = SuperAdmin

$clientAccess = 0; //0 = Client canot view, 1 = client can view

$_SESSION['redirect'] = basename($_SERVER['SCRIPT_FILENAME']);

$rootfile = 1;

// INCLUDES

require('includes/includes.php'); // Database functions

// STANDARD PAGE SPECIFIC VARIABLE SET

$title = "Install Check"; //Page Title - Must be before filestart

require('includes/filestart.php');

//GET POST INFO FROM FORM RESUBMIT

if($_SERVER['REQUEST_METHOD'] == "POST") {

  //GET LOCATION INFO FROM FORM RESUBMIT

  if(isset($_POST['loc'])) {

    $loc = $_POST['loc'];

  } else {

    $loc = null;

  }

  //GET ROOM INFO FROM FORM RESUBMIT

  if(isset($_POST['Room'])) {

    $Room = $_POST['Room'];

  } else {

    $Room = null;

  }

  //GET TYPE INFO FROM FORM RESUBMIT (OPTIONAL)

  if($_POST['type'] > 0 ) {

    $type = $_POST['type'];

    $typeSQL = " AND A.assetType = $type ";

  } else {

    $type = null;

    $typeSQL = null;

  }

}

//FUNCTION FOR INSTALLED BUTTON

install()

?>

<div class="d-md-none">

  <div style="margin-top: 100px"></div>

</div>

<div class='container1'>

  <form name="installform" method="post" role="form" >

    <div class="col-md-11 container-flex mx-auto">

      <div class="col-11 form-location mx-auto">

        <select class='form-select' name='loc' value='<?php echo $loc ?>' onchange='this.form.submit()'></option>

          <option value=''>Choose Location</option>";

          <?php  

            //LOCATION DROP DOWN

            $SQL = "SELECT L.id, L.LocationName FROM asset A JOIN loc L ON A.loc = L.id GROUP BY L.LocationName ORDER BY L.id";

            $list = query($SQL);

            if(is_array($list) || is_object($list)) {

            foreach($list as $row) {

                echo "<option value='".$row['id']."'";

                IF($row['id'] == $loc) {

                echo " selected>".$row['LocationName']."</option>";

                } else {

                echo ">".$row['LocationName']."</option>";

                }

            }

            }

          ?>

        </select>

      </div>

    </div>

    <?php

      //IF LOCATION IS SELECTED SHOW ROOM DROP DOWN

      if($loc > 0 ) {

    ?>

    <div class="col-md-11 container-flex mx-auto mt-2">

      <div class="col-11 form-location mx-auto">

        <select class='form-select' name='Room' value='' onchange='this.form.submit()'></option>

          <option value=''>Choose Room</option>

          <?php  

            //ROOM DROP DOWN

            $SQL1 = "SELECT A.Room, R.room FROM asset A LEFT JOIN room R ON R.roomNo = SUBSTRING(A.Room,1,3) WHERE A.Room != '' AND A.loc = $loc GROUP BY A.Room ORDER BY A.Room";

            $list1 = query($SQL1);

            if(is_array($list1) || is_object($list1)) {

              foreach($list1 as $row) {

                echo "<option value='".$row['Room']."'";

                IF($row['Room'] == $Room) {

                  echo " selected>".$row['Room']." ".$row['room']."</option>";

                } else {

                  echo ">".$row['Room']." ".$row['room']."</option>";

                }

              }

            }

          ?>

        </select>

      </div>

    </div>

    <?php

      }

     

      //IF LOCATION AND ROOM IS SELECTED SHOW TYPE DROP DOWN

      if($loc > 0 && $Room > 0) {

    ?>

    <div class="col-md-11 container-flex mx-auto mt-2">

      <div class="col-11 form-location mx-auto">

        <select class='form-select mb-2' name='type' value='' onchange='this.form.submit()'></option>

          <option value=''>Choose Type (Optional)</option>

          <?php  

            //TYPE DROP DOWN

            $SQL2 = "SELECT T.assetTypeID, T.assetType FROM asset A LEFT JOIN assettype T ON T.assetTypeID = A.assetType WHERE A.ROOM = '$Room' AND A.loc = $loc GROUP BY T.assetType ORDER BY T.assetType";

            $list2 = query($SQL2);

            if(is_array($list2) || is_object($list2)) {

              foreach($list2 as $row) {

                  echo "<option value='".$row['assetTypeID']."'";

                  IF($row['assetTypeID'] == $type) {

                  echo " selected>".$row['assetType']."</option>";

                  } else {

                  echo ">".$row['assetType']."</option>";

                  }

              }

            }

          ?>

        </select>

      </div>

    </div>

       

  </form>

  <div class="container-fluid ms-7 w-auto">

  <div class="card">

    <div class="card-body">

      <div id='' class='content'>

        <table id='assyntCx_Table' class='display' style="width:100%">

          <thead>

            <tr>

              <th style='width: 36%;'>Design Tag</th>

              <th style='width: 36%;'>Spec Tag</th>

              <th style='width: 36%;'>Asset</th>

              <th style='width: 28%; text-align: right'>Status</th>

            </tr>

      </thead>

      <tbody>

  <?php

    $SQL3 = "SELECT A.id, A.dwgTag, Z.assetTag, T.assetType, A.assetStatus, S.assetStatus FROM asset A LEFT JOIN assetstatus S ON S.id = A.assetStatus LEFT JOIN assetTag Z ON Z.assetID = A.id LEFT JOIN assettype T ON T.assetTypeID = A.assetType WHERE A.loc = $loc AND A.Room = '$Room' $typeSQL ORDER BY A.dwgTag";

    if($result3 = query($SQL3)) {

      while ($row3 = mysqli_fetch_array($result3)) {

        $assetID = $row3[0];

        echo "

      <form name='installform' method='post' role='form' >

        <input type='hidden' name='loc' id='loc' class='form-control' value='$loc'>

        <input type='hidden' name='Room' id='Room' class='form-control' value='$Room'>

        <input type='hidden' name='assetID' id='assetID' class='form-control' value='$assetID'>

        <tr>

          <td style='width: 36%'><small>$row3[1]</small></td>

          <td style='width: 36%'><small>$row3[2]</small></td>

          <td style='width: 36%'><small>$row3[3]</small></td>";

      if($row3[4] == 1) {

        echo "

          <td class='text-center'>

            <button type='submit' class='btn btn-danger btn-sm' name='install' value='3'><small>None</small></button>

          </td>";

      } elseif($row3[4] == 3) {

        echo "

          <td class='text-center'>

            <button type='submit' class='btn btn-warning btn-sm' name='uninstall' value='1'><small>Installed</small></button>

          </td>";

      } else {

        echo "

          <td class='text-center'>

            <button type='button' class='btn btn-success btn-sm' disabled><small>Tested</small></button>

          </td>";

      }

        echo "

        </tr>

      </form>";

    }

  }

  echo "

      <tbody>

    </table>

    </div>

    </div>

  </div>

</div>

   

  ";

}

?>

</div>

<script>

$(document).ready(function() {

    $('#assyntCx_Table').DataTable( {

       

        dom: 'fit',

        scrollY:        '65vh',

        scrollCollapse: true,

        paging:         false

    } );

} );

</script>

<?php require('includes/fileend.php') ?>

You would use ajax to submit the form data to the server and to put the returned markup for the 2nd and 3rd selects, and for the datatable, into the desired location on the page.

Here’s an example for three chained selects that should be easy to add the datatable markup to.
Main file -

<form action="ajax.php" method="post">
	<input type='hidden' name='action' value='chained select'>
	<select name='loc' class='ajaxSelect'>
	<option value=''>Choose Location</option>
	<option value='1'>l1</option>
	<option value='2'>l2</option>
	<option value='3'>l3</option>
	<option value='4'>l4</option>
	</select>
	<div id='sel2'></div>
	<div id='sel3'></div>
	<div id="server-message"></div>
</form>

<script
  src="https://code.jquery.com/jquery-3.6.0.min.js"
  integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="
  crossorigin="anonymous">
</script>

<script>
$(document).ready(function () {
		$(document).on('change','.ajaxSelect',function(){
		var parentForm = $(this).closest("form")[0];
		var post_url = $(parentForm).attr('action');
		var request_method = $(parentForm).attr('method');
		var form_data = new FormData(parentForm);
		$.ajax({
			url : post_url,
			type: request_method,
			data : form_data,
			contentType: false,
			cache: false,
			processData:false,
			dataType: 'json'
		}).done(function(data){
			var val_s = data.val; // text and textarea values
			if(val_s){
				$.each(val_s, function(key, value){
					$(key).val(value);
				});
			}
			var html_s = data.html; //inner html
			if(html_s){
				$.each(html_s, function(key, value){
					$(key).html(value);
				});
			}
			var styl_s = data.styles; //css class name
			if(styl_s){
				$.each(styl_s, function(key, value){
					$(key).attr("class", value);
				});
			}
			var sel_s = data.sel; // select/option - selected
			if(sel_s){
				$.each(sel_s, function(key, value){
					var v = value != '' ? true : false;
					$(key).prop("selected", v);
				});
			}
			var check_s = data.che; // radio and checkbox - checked
			if(check_s){
				$.each(check_s, function(key, value){
					var v = value != '' ? true : false;
					$(key).prop("checked", v);
				});
			}
		});
	});
});
</script>

The main points in the above are that each select has a class attribute ajaxSelect, so that the on change event will work with it, that there are two div tags with unique ids to put the generated select markup into, and that the javascript is general-purpose and should not require touching for each different value. Note: only the section of javascrupt for data.html is used.

ajax.php

<?php
if($_SERVER['REQUEST_METHOD'] == 'POST')
{
	switch ($_POST['action'])
	{
		case 'chained select':
			// code for 2nd select
			// if a previous selection is empty, clear remainder
			// i.e. if loc is empty, clear county and town
			// if county is empty, clear town
			if(empty($_POST['loc']))
			{
				$_POST['county'] = '';
				$_POST['town'] = '';
			}
			if(empty($_POST['county']))
			{
				$_POST['town'] = '';
			}

			// if there is not a loc, output '' to clear the existing dom
			// if there is a loc and not a county generate and output the select
			// if there is a loc and a county don't include anything in the output
			// i.e. if there is not a loc or there is not a county, include the content in the output
			$content_counties = '';
			if(!empty($_POST['loc']) && empty($_POST['county']))
			{
				$result_counties = [];
				// fake some data - you would query for and retrieve the actual data here...
				$result_counties[] = ['id'=>1, 'name'=>$_POST['loc']."c1"]; // the use of the post loc prefix in the name value is just to produce unique values to show that loc was present.
				$result_counties[] = ['id'=>2, 'name'=>$_POST['loc'].'c2'];
				$result_counties[] = ['id'=>3, 'name'=>$_POST['loc'].'c3'];
				$result_counties[] = ['id'=>4, 'name'=>$_POST['loc'].'c4'];

				if(!empty($result_counties))
				{
					$content_counties = "<select name='county' class='ajaxSelect'>
					<option value=''>Select a County</option>";
					foreach($result_counties as $row){
						$content_counties .= "<option value='{$row['id']}'>{$row['name']}</option>";
					}
					$content_counties .= "</select>";
				}
			}
			if(empty($_POST['loc']) || empty($_POST['county']))
			{
				// the 'html' key indicates the data is to be used as inner html in the dom
				// the 2nd key is a jquery selector to use for where the html will be put
				$array['html']['#sel2'] = $content_counties;
			}

			// code for 3rd select
			// if there is not a loc or not a county, output '' to clear the existing dom
			// if there is a loc and a county and not a town generate and output the select
			// if there is a loc and a county and a town don't include anything in the output
			// i.e. if there is not a loc or there is not a county or there is not a town, include the content in the output
			$content_towns = '';
			if(!empty($_POST['loc']) && !empty($_POST['county']) && empty($_POST['town']))
			{
				$result_towns = [];
				// fake some data - you would query for and retrieve the actual data here...
				$result_towns[] = ['id'=>1, 'name'=>$_POST['county']."t1"];
				$result_towns[] = ['id'=>2, 'name'=>$_POST['county'].'t2'];
				$result_towns[] = ['id'=>3, 'name'=>$_POST['county'].'t3'];
				$result_towns[] = ['id'=>4, 'name'=>$_POST['county'].'t4'];

				if(!empty($result_towns))
				{
					$content_towns = "<select name='town' class='ajaxSelect'>
					<option value=''>Select a Town</option>";
					foreach($result_towns as $row){
						$content_towns .= "<option value='{$row['id']}'>{$row['name']}</option>";
					}
					$content_towns .= "</select>";
				}
			}
			if(empty($_POST['loc']) || empty($_POST['county']) || empty($_POST['town']))
			{
				$array['html']['#sel3'] = $content_towns;
			}

			// this entry is just a message
			$array['html']["#server-message"] = 'done';
			echo json_encode($array);

		break;
	}
}

The main point in the above is that the markup is built in php variables that are then output as json_encode data back to the browser, where the javascript takes it and puts it into the desired locations on the page.

Also, don’t put external, unknown, dynamic values directly into sql query statements. Use a prepared query instead.

@phdr Hello.Thank you so much for example and explanation. I will try to make my page using ajax. But I am not sure…how to do that for my specific data. The data I am fetching from database which is stored in tables. Its not Json data. so for now if I try to fetch data for just First Dropdown … I did as below. Please check my both file code.

Controller file - install1.php

<?php

include_once("../lib/DataTables.php");

$loc = $db

    ->select( 'loc',

    ['id as value', 'LocationName as label'], ['LocationName' => $_REQUEST['values']['LocationName']])

   

    ->fetchAll();

 //echo json_encode( $loc );

echo json_encode( [

    'options' => [

        'location' => $loc,

    ]

] );

         

?>

In above code I am trying to fetch data fron ‘loc’ table where LocationName column has all the locations which I want to display for First Dropdown - Location.

main.php

<?php

//SESSION START

if(!isset($_SESSION)) {

  session_start();

}

$actual_link = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";

if (strpos($actual_link, 'test.assettrack')) {

  $path ="https://test.assettrack.cx";

} else {

  $path = "https://assettrack.cx";

}

//PERMISSIONS (REQUIRED IN INCLUDE)

$public = 1; // 0 = Have to be logged in, 1 = Anyone can view.

$permission = 15; //10 = User, 20 = Tester, 30 = Admin, 40 = SuperAdmin

$clientAccess = 0; //0 = Client canot view, 1 = client can view

$_SESSION['redirect'] = basename($_SERVER['SCRIPT_FILENAME']);

$rootfile = 1;

// INCLUDES

require('includes/includes.php'); // Database functions

// STANDARD PAGE SPECIFIC VARIABLE SET

$title = "Install Check"; //Page Title - Must be before filestart

require('includes/filestart.php');

//GET POST INFO FROM FORM RESUBMIT

if($_SERVER['REQUEST_METHOD'] == "POST") {

  //GET LOCATION INFO FROM FORM RESUBMIT

  if(isset($_POST['location'])) {

    $loc = $_POST['location'];

  } else {

    $loc = null;

  }

 

}



?>

<div class="d-md-none">

  <div style="margin-top: 100px"></div>

</div>

<div class='container1'>

  <form name="installform" method="post" role="form" >

    <div class="col-md-11 container-flex mx-auto">

      <div class="col-11 form-location mx-auto">

        <select class='form-select' name='location' value='<?php echo $loc ?>' onchange='this.form.submit()'></option>

          <option value=''>Choose Location</option>";
        </select>

      </div>

    </div>

<script>

$(document).ready(function() {

    //$('#loc').getJSON("../ajax/at/install1.php");

    // $('#loc').change( function(){

       

    //      $.getJSON("../ajax/at/install1.php");

    //   }  

     

      //     function(result){

        //         // $.each(result, function(i, field){

        //         //     $("div").append(field + " ");

        //         // });

        //     });

        // // e.preventDefault();

        //  alert(e.cancelable?"Is cancelable":"Not cancelable");

    //$('#loc').click( function(data){

                             

     var data = $.getJSON('../ajax/at/install1.php',

                       

                function (data) {

                   

                    console.log(data);

                   

                }

     );

   

    $('#assyntCx_Table').DataTable( {

       

        dom: 'fit',

       

        scrollY:        '65vh',

        scrollCollapse: true,

        paging:         false

    });

} );

</script>

<?php require('includes/fileend.php') ?>

In above code I tried to use ‘$.getJSON’ to get converted data (from database table to json).
I know there is something wrong with both the files. Specially I am not good in JS… and I tried using online solution but… I am not getting any value in Location Dropdown. It only displays blank dropdown.

Here is the link : https://test.assettrack.cx/install1.php

Sponsor our Newsletter | Privacy Policy | Terms of Service