Home > front end >  Populate dynamic dropdown, Codeigniter
Populate dynamic dropdown, Codeigniter

Time:05-13

I'm trying to make a dynamic dropdown with Codeigniter but I'm having trouble getting the values on the next dropdown. When I select and option on the first dropdown, the second dropdown is not populated:

enter image description here

I'm also not familiar at using AJAX, I only write the script based on what I searched so please teach me what to do to make the dynamic dropdown work.

This is my Model:

public function category()
{
    $this->db->order_by("category", "ASC");

    $query = $this->db->get('categories');
    return $query->result();
}

function get_subcategory($parent_id)
{
    $this->db->where('parent_id', $parent_id);
    $this->db->order_by('sub_category', 'ASC');
    $query = $this->db->get('sub_categories');
    $output = '<option value="">Select Sub-Category</option>';
    foreach ($query->result() as $row) {
        $output .= '<option value="' . $row['id'] . '">' . $row['sub_category'] . '</option>';
    }
    return $output;
}

My Controller:

public function category()
{
    $data['title'] = 'List of Category';

    $this->load->view('../admin/template/admin_header');
    $this->load->view('../admin/template/admin_topnav');
    $this->load->view('../admin/template/admin_sidebar');
    $this->load->view('../admin/category/category', $data);
    $this->load->view('../admin/template/admin_footer');
}

function get_subcategory()
{
    if ($this->input->post('parent_id')) {
        echo $this->Admin_model->get_subcategory($this->input->post('parent_id'));
    }
}

View:

<div >
    <label for="" >Category</label>
    <select name="category" id="category"  required>
        <option value="">- Select Category -</option>
        <?php
            foreach ($category as $row) {
                echo '<option value="' . $row->id. '">' . $row->category . '</option>';
            }
        ?>
    </select>
</div>
<div >
    <label for="" >Sub Category</label>
    <select name="sub_category" id="sub_category_id"  required>
        <option value="">- Select Sub Category -</option>
    </select>
</div>

And script:

$(document).ready(function() {
    $('#category').change(function() {
        var parent_id = $('#category').val();
        if (parent_id != '') {
            $.ajax({
                url: "<?php echo base_url(); ?>admin/get_subcategory",
                method: "POST",
                data: {parent_id:parent_id},
                success: function(data) {
                    $('#sub_category_id').html(data);
                }
            });
        } else {
            $('#sub_category_id').html('<option value="">Select Sub Category</option>');
        }
    });
});

CodePudding user response:

In your success response write this and remove the else from down there.

success: function(data) {
  $('#sub_category_id').append('<option value=>Select Sub Category</option>');
  for (var i=0; i<data.length; i  ) { 
    $('#sub_category_id').append($('<option>', { 
      value: data[i].id,
      text : data[i].sub_category
    }));
  }
}

get AJAX response in the array from your controller and then run this through javascript like this.

id is id from your db and sub_category is sub_category coming from your db

with ajax response array.

CodePudding user response:

Your question doesn't mention it, but your CSS suggests your selects are actually using Select2. When you initialise a select as a Select2, it makes a copy of the initial HTML, and adds styling and JS to it, and it is the copy that you see and interact with. The original HTML is no longer visible or used at all.

So if you later come along and modify that original HTML, it will have no effect on the Select2 you already generated and can see an interact with on the page.

One solution is to reinitialise that Select2 after you modify it.

UPDATE

I've added a working snippet, with some hard-coded HTML to simulate what your AJAX returns. Click run to try it.

$(document).ready(function () {
    
    // Initialise Select2s
    $('.select2').select2();
    
    // Fake HTML, simulate what your AJAX returns
    let fakedHTMLResponse = '<option value="water">Water</option><option value="juice">Juice</option><option value="beer">Beer</option>';
    
    $('#category').change(function () {
        var parent_id = $('#category').val();
        // console.log('parent_id', parent_id);
        
        if (parent_id != '') {
            // Your AJAX call happens here, let's simulate the success
            // response it gets back, and handle it the same way.
            $('#sub_category_id').select2('destroy')
                .html(fakedHTMLResponse)
                .select2();

        } else {
            $('#sub_category_id').html('<option value="">Select Sub Category</option>');
        }
    });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/select2.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/select2.min.js"></script>

<select id="category"  name="food">
    <option value="">- Select Category -</option>
    <option value="fruits">Fruits</option>
    <option value="vegetables">Vegetables</option>
    <option value="cakes">Cakes</option>
</select>

<select id="sub_category_id"  name="drink">
    <option value="">- Select Sub Category -</option>
</select>

Note:

  • Convention is to use GET when retrieving data, and POST for changing data. Your AJAX calls are just retrieving data to display, so really should be GET;

  • If you are going to use a jQuery selector more than once, it makes sense to cache them. Eg in the above code you should do something like:

    let $category = $('#category');
    let $sub = $('#sub_category_id');
    
    // And then every time you need to use that selectors, use the variable, eg:
    $category.select2();
    $category.change(function ...
    $sub.select2('destroy');
    // etc
    
  • Related