I'm trying to create a Dynamic Dependent Dropdown via Ajax and CodeIgniter 4. However, I could not make it work. Can you help me figure out what's wrong? I'm trying to follow this tutorial online: LINK
Error on the console
jquery.min.js:2
POST http://localhost/sidsci/public/sd/getAjaxBrgy 500 (Internal Server Error)
Database
mcb_id | mcb_name | mcb_brgy
View
<div class="form-row">
<div class="form-group col-md-6">
<label><b>Municipal / City<span class="text-danger">*</span></b></label>
<select name="s_muncity" class="form-control" id="s_muncity" required>
<option value="">-Select-</option>
<?php foreach($mcb as $mcb_row):?>
<option value="<?= $mcb_row->mcb_name;?>"><?= $mcb_row->mcb_name;?></option>
<?php endforeach;?>
</select>
</div>
<div class="form-group col-md-6">
<label><b>Barangay<span class="text-danger">*</span></b></label>
<select class="form-control" name="s_brgy" id="s_brgy" required></select>
</div>
</div>
$('#s_muncity').change(function(){
var mcb_name = $(this).val();
$.ajax({
url:'<?=base_url('/sd/getAjaxBrgy')?>',
method: 'POST',
data: {mcb_name: mcb_name},
dataType: 'json',
success: function(response){
$('#s_brgy').find('option').not(':first').remove();
$.each(response,function(index,data){
$('#s_brgy').append('<option value="'+data['mcb_brgy']+'">'+data['mcb_brgy']+'</option>');
});
}
});
});
Controller
public function getAjaxBrgy(){
$model = new McbModel();
$postData = array(
'mcb_name' => $this->request->getPost('mcb_name'),
);
$data = $model->getBrgyData($postData);
echo json_encode($data);
}
Model
public function getBrgyData($postData) {
$sql = 'select mcb_brgy from mcb where mcb_name ='.$postData['mcb_name'];
$query = $this->db->query($sql);
return $query->getResult();
}
I also have <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
in my header part.
In the View markup, identify options reliably by assigning the database id as the option value
attribute value. In the great majority of cases, relationships should be built on ids, not names.
<div class="form-row">
<div class="form-group col-md-6">
<label for="s_muncity">
<b>Municipal / City<span class="text-danger">*</span></b>
</label>
<select name="s_muncity" class="form-control" id="s_muncity" required>
<option value="">-Select-</option>
<?php foreach ($mcb as $mcb_row) { ?>
<?php printf('<option value="%d">%s</option>', $mcb_row->mcb_id, $mcb_row->mcb_name); ?>
<?php } ?>
</select>
</div>
<div class="form-group col-md-6">
<label for="s_brgy"><b>Barangay<span class="text-danger">*</span></b></label>
<select class="form-control" name="s_brgy" id="s_brgy" required>
<option value="">-Select-</option>
</select>
</div>
</div>
In your Javascript, if you aren't going to use mcb_id as option values, then omit the value
attribute value entirely -- there is no benefit in repeating the option's text as the value
attribute. This ajax request is merely "reading" data (not "writing") data, therefore it is generally accepted practice to perform a GET request rather than a POST request.
$('#s_muncity').change(function() {
$.get(
'<?php echo base_url("/sd/getAjaxBrgy/"); ?>' + $(this).val(),
function (response) {
$('#s_brgy').find('option').not(':first').remove();
$.each(response, function(index, data) {
$('#s_brgy').append(
'<option>' + data.mcb_brgy + '</option>'
);
});
},
'json'
);
});
The Controller
public function getAjaxBrgy(int $mcbId)
{
echo json_encode(
(new McbModel())->getBrgy(['mcb_id' => $mcbId])
);
}
The Model: (your earlier attempt was not quoting the variable being passed in -- I assume the value was not an integer or float)
public function getBrgy(array $where, string $order = 'mcb_name'): array
{
return $this->db
->table('mcb_brgy')
->orderBy($order)
->getWhere($where)
->getResult();
}
All that said, I wouldn't perform any AJAX requests at all!
Since you already have a single result set that contains all of the database table data, you should declare a lookup object in javascript as a constant. The properties will be the mcb_id values and the values for each mcb_id will be a subarray containing all related mcb_brgy values.
Everything you need will be readily available for instant Javascript access and you won't need to bother your server.
Populating the lookup:
const mcbLookup = <?php echo json_encode(
array_reduce(
$mcv,
function ($result, $row) {
$result[$row->mcb_id][] = $row->mcb_brgy;
return $result;
},
[]
)
); ?>;
Adding the listener:
$('#s_muncity').change(function(){
$('#s_brgy').find('option').not(':first').remove();
$.each(
mcbLookup[$(this).val()],
function(index, data) {
$('#s_brgy').append('<option>' + data.mcb_brgy + '</option>');
}
);
});