Jump to content

Display options conditionally in <select> element


Go to solution Solved by Barand,

Recommended Posts

Hello Freaks and Geeks, I hope the weekend is seeing you all healthy and happy. I've been debating the proper implementation of a task. Hoping to find someone sitting in front of the computers feeling helpful. I believe I need to JS/AJAX for this, so I hope I'm in the right forum

I have a form. In that form there's a  <select> dropdown for a 'category' and one for 'type' of contribution. I'd like to make it so that the options available in the category dropdown are conditional on what was chosen in the type dropdown.

So if I had the following PHP ->

<?php

 <div class="form-group">
    <label>Category</label>
    <select class="form-control" name="cat_id" id="category">
        <?php 
           if(!$this) {
               echo $post->selectCat('top');
           } else {
               echo $post->selectCat('actor');
           }
        ?>
    </select>
</div>

the "(!this)" in the if condition is meant only as a placeholder to keep the error notis away in my IDE and does nothing, nor was ever expected to.

So in this implementation I thought to have 2 methods. Create a JS boolean function and either call selectCat('top') or selectCat('actor') depending on what the JS returned.

I could also, though not sure how yet, call the PHP methods directly from the JS.

What would be the best way to complete this task? The way I started with, the other way I mentioned, another way I haven't thought about??

All advice, input and criticism welcome.. TIA and the best to you all during these messy times

 

 

  • Solution

This example will repopulate the category menu depending on the selected type

<html>
<head>
<title>Sample</title>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type='text/javascript'>

// array of categories for each type
var cat_types = JSON.parse('{"A":{"1":"Cat 1","2":"Cat 2","3":"Cat 3"},"B":{"4":"Cat 4","5":"Cat 5","6":"Cat 6"},"C":{"7":"Cat 7","8":"Cat 8","9":"Cat 9"}}');

    $().ready(function() {
        // populate type menu
        $.each(cat_types, function(k,v) {
            $("#type").append($("<option>", {"val":k, "text":k}))
        })
        
        // when type selected, populate cat menu
        $("#type").change( function() {
            $("#cat").html("<option value=''> - select category -</option");
            var type = $(this).val()
            $.each(cat_types[type], function(k, v) {
                $("#cat").append($("<option>", {"val":k, "text":v}))
            })
        })
    })
</script>
<style type='text/css'>

</style>
</head>
<body>
<form>
     Type <select name='type' id='type'>
             <option value=""> - select type -</option>
          </select>
          <br><br>
     Cat  <select name='cat' id='cat'></select><br>
</form>
</body>
</html>

 

  • Great Answer 1

Hay, Barand, Thanks for your answer. I'm playing around with it now. I've got it populating correctly in the actual project but realize I'll have an issue soon.

The <select> menu for the categories was originally populated by a PHP method which used the cat id from the database as the value in the <option> element.

I was the method I was calling in the OP is ->

<?php

public function selectCat($type) {
      $table = "categories";
      $field = "type";
      // $type = "top";
      $rule = "ORDER BY id ASC";
      $query = $this->_db->get($table, array($field, "=", $type), $rule);

      $this->_data = $query->all();

      $str = "";
      foreach($this->_data as $obj) {
          $cat_id = $obj->id;
          $category = $obj->category;
          $title = ucwords($category);

          $str .= "
          <option value='$cat_id'>$title</option>
      ";
      }
      return $str;
  }

So I'm thinking I'll rewrite this method to return your JSON.parse($string)

Quote

'{"A":{"1":"Cat 1","2":"Cat 2","3":"Cat 3"},"B":{"4":"Cat 4","5":"Cat 5","6":"Cat 6"},"C":{"7":"Cat 7","8":"Cat 8","9":"Cat 9"}}'

replacing "A", "B", "C" etc with  the values from the type field; "1", "2", "3" etc keys with cat ids and "Cat 1", "Cat 2", "Cat 3" etc with the category names... you get the picture.

In your very experienced opinion is this the best way to do this or would you suggest a different way?

It's one way, and if I didn't have a database, it's as good a way as any. If I did have a DB I'd do it differently. But given no information to the contrary, I did it that way. A DB solution would use elements of that code, such as building the category menu.

14 minutes ago, Barand said:

It's one way, and if I didn't have a database, it's as good a way as any. If I did have a DB I'd do it differently. But given no information to the contrary, I did it that way. A DB solution would use elements of that code, such as building the category menu.

Ok, thank you. I'm going to work on creating that string in a PHP method, I'm part way there as I type. I hope you can respond again if I have to readdress this issue lol

Thanks again

Using a DB, I'd do it this way (tables used are from my SQL tutorial). Select a house name and the pupils menu lists pupils from that house.

<?php
const HOST     = 'localhost'; 
const USERNAME = '????';                                                                
const PASSWORD = '????';                                                                
const DATABASE = 'jointute';               // default db

$db = pdoConnect();


//==============================================================================
//  HANDLE AJAX CALLS
//                                   
    if (isset($_GET['ajax'])) {
        
        if ($_GET['ajax']=='pupilopts') {
            exit( json_encode(pupilOptions($db, $_GET['hid'])));
        }
        
        exit('INVALID REQUEST');
    }
//==============================================================================


function houseOptions($db)
{
    $opts = "<option value=''>- select house -</option>\n";
    $res = $db->query("SELECT houseID
                           , house_name
                      FROM house
                      ORDER BY house_name
                     ");
    foreach ($res as $r) {
        $opts .= "<option value='{$r['houseID']}'>{$r['house_name']}</option>\n";
    }
    return $opts;
}


function pupilOptions($db, $hid)
{
    $opts = [];
    $res = $db->prepare("SELECT pupilID
                              , CONCAT(lname, ', ', fname) as name
                         FROM pupil
                         WHERE houseID = ?
                         ORDER BY lname, fname     
                        ");
    $res->execute([$hid]);
    $pups = $res->fetchAll();
    $opts = array_column($pups, 'name', 'pupilID');
    sort($opts);
    return $opts;
}

                                                                                       
function pdoConnect($dbname=DATABASE)                                                   
{                                                                                       
    $db = new PDO("mysql:host=".HOST.";dbname=$dbname;charset=utf8",USERNAME,PASSWORD); 
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);                       
    $db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);                  
    $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);                               
    return $db;                                                                         
}
                                                                                       
?>
<!DOCTYPE html>
<html lang='en'>
<head>
<title>Example</title>
<meta charset='utf-8'>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type='text/javascript'>
    $().ready( function() {
        
        $("#houses").change( function() {
            var hid = $(this).val()
            $.get(
                "",                                                // specify processing file on server (in this case it's same file)
                {"ajax":"pupilopts", "hid":hid},                   // data to send in request
                function(resp) {                                   // handle the response
                    $("#pupils").html("<option value=''> - select pupil -</option");
                    $.each(resp, function(k, v) {
                        $("#pupils").append($("<option>", {"val":k, "text":v}))
                    })
                },                                                  
                "JSON"                                              // response type
            )
        })
    })
</script>
<style type='text/css'>
    body {
        font-family: calibri, sans-serif;
        font-size: 12pt;
    }
    div {
        margin: 16px;
        padding: 8px;
        border: 1px solid gray;
    }
    label {
        display: inline-block;
        background-color: black;
        color: white;
        width: 120px;
        padding: 8px;
        margin: 1px 8px;
    }
</style>
</head>
<body>
    <div>
        <label>House</label> 
        <select id="houses" >
             <?= houseOptions($db) ?>
        </select>
    </div>
    <div>
        <label>Pupil</label> 
        <select id="pupils" >
             <!-- pupil options -->
        </select>
    </div>
</body>
</html>

 

  • Like 2
This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.