Objective:
Based on the example found here. Populating dependent drop-downs with the data parsed in the getData()
function using ajax calls. Currently my example is working with static data found in the ajax-mocks.js
file, but I am unable to understand how to parse the data properly into the drop-downs, as well as populating the other drop-downs as previously done with the sample mockjax data calls.
Resources:
KnockoutJS - Loading/Saving Json Data
functions.php
Renders HTML to woocommerce front-end product page
function add_custom_toga_fields() {
if( has_term('toga', 'product_cat' ) ) {
?>
<p class="label-description"><span>1. Details</span></p>
<table id="graduation" class="custom-fields .bs-docs-example" cellspacing="0">
<tbody>
<tr>
<td class="label"><label for="institution">Institution<span class="required">*</span></label></td>
<td class="value">
<select name="institution" id="institution" class="step1 select2">
<option value="">Select institution</option>
</select>
</td>
</tr>
<tr>
<td class="label"><label for="level">Level of Award<span class="required">*</span></label></td>
<td class="value">
<select name="level" id="level" class="step2 select2">
<option value="">Select level</option>
</select>
</td>
</tr>
<tr>
<td class="label"><label for="faculty">Faculty<span class="required">*</span></label></td>
<td class="value">
<select name="faculty" id="faculty" class="step3 select2">
<option value="">Select Faculty</option>
</select>
</td>
</tr>
<tr>
<td class="label"><label for="ceremony-date">Ceremony Date<span class="required">*</span></label></td>
<td class="value">
<input name="ceremony" type="text" id="ceremony">
</td>
</tr>
<tr>
<td>
<h4>Matches <img src="<?php echo get_stylesheet_directory_uri(); ?>/assets/icons/ajax-loader.gif" data-bind="visible: loading" /></h4>
<ul class="colour-results-list" data-bind="foreach: colours, visible: colours().length > 0">
<li style="background: red;">
<span class="colour-hat" data-bind="text: colour" style="background: yellow;"></span>
</li>
</ul>
</td>
</tr>
</tbody>
</table>
<?php
}
}
add_action( 'woocommerce_before_variations_form', 'add_custom_toga_fields' );
class-system-public.php
Get data from database and process it to correct format
public function get_data() {
global $wpdb;
$result = array();
$records = $wpdb->get_results("CALL get_json_data");
foreach($records as $record) {
$obj = new stdClass();
$obj->institution = $record->universityid;
$obj->level = $record->levelid;
$obj->faculty = [];
$faculties = $wpdb->get_results("CALL get_courses_and_colour_by_university_and_level($obj->institution, $obj->level)");
foreach($faculties as $faculty) {
$facObj->name = $faculty->name;
array_push($obj->faculty, $facObj->name);
}
array_push($result, $obj);
}
echo json_encode($result);
wp_die();
}
custom-dropdown.js
Builds Dependent Cascading Drop-down
jQuery(document).ready(function() {
// Apply Select 2
jQuery(".select2").select2();
function getInstitutions() {
var results = [
{ label: 'Test 1', value: 1 },
{ label: 'Test 2', value: 2 },
{ label: 'Test 3', value: 3 },
]
return results;
}
function viewmodel() {
this.colours = ko.observableArray([]);
this.loading = ko.observable(false);
}
var graduation = new viewmodel();
ko.applyBindings(graduation, document.getElementById('graduation'));
jQuery('#graduation').cascadingDropdown({
selectBoxes: [
{
selector: '.step1',
source: getInstitutions()
},
{
selector: '.step2',
requires: ['.step1'],
source: function(request, response) {
jQuery.getJSON('/api/levels', request, function(data) {
var selectOnlyOption = data.length <= 1;
response(jQuery.map(data, function(item, index) {
return {
label: item,
value: item,
selected: selectOnlyOption
};
}));
});
}
},
{
selector: '.step3',
requires: ['.step1', '.step2'],
requireAll: true,
source: function(request, response) {
jQuery.getJSON('/api/faculties', request, function(data) {
response(jQuery.map(data, function(item, index) {
return {
label: item,
value: item,
selected: index == 0
};
}));
});
},
onChange: function(event, value, requiredValues, requirementsMet) {
if(!requirementsMet) return;
graduation.loading(true);
var ajaxData = requiredValues;
ajaxData[this.el.attr('name')] = value;
jQuery.getJSON('/api/colours', ajaxData, function(data) {
graduation.colours(data);
graduation.loading(false);
});
}
}
]
});
});
ajax-mock.js
Some mockjax data to simulate ajax call
// Some mockjax code to simulate Ajax calls
var colourList = [
{
faculty: [8, 16],
institution: 2,
level: "Bachelors",
colour: 'Red'
},
{
faculty: [32, 64],
institution: 3,
level: "Doctorate",
colour: 'Green'
},
{
institution: 2,
level: "Bachelors",
faculty: [8],
colour: 'Blue'
},
{
faculty: [16],
institution: 3,
level: "Masters",
colour: 'Purple'
},
{
faculty: [16],
institution: 3,
level: "Masters",
colour: 'Pink'
},
{
faculty: [16, 32],
institution: 1,
level: "Masters",
colour: 'Brown'
},
{
level: 2,
faculty: ["Msc Business Information System Management"],
institution: 3,
colour: 'Gray'
}
];
getData();
function getData() {
var data = { 'action': 'get_data' };
var deferred = new jQuery.Deferred();
return jQuery.post(ajaxurl, data, function(response) {
var obj = JSON.parse(response);
results = obj;
}).done(function() {
return deferred.resolve(results);
}).fail(function() {
});
}
function arrayIntersect(a, b) {
return jQuery.grep(a, function(i) {
return jQuery.inArray(i, b) > -1;
});
}
function arrayToInt(array) {
var output = [];
for(var i=0;i<array.length;i++) {
if(array[i] && !isNaN(+array[i])) output.push(+array[i]);
}
return output;
}
function arrayToFloat(array) {
var output = [];
for(var i=0;i<array.length;i++) {
if(array[i] && !isNaN(parseFloat(array[i]))) output.push(parseFloat(array[i]));
}
return output;
}
function getColours(institution, level, faculty) {
var _institution = arrayToFloat([].concat(institution)),
_level = arrayToInt([].concat(level)),
_faculty = arrayToInt([].concat(faculty));
return jQuery.grep(colourList, function(item, index) {
var i = true, l = true, f = true;
if(_institution.length) {
i = jQuery.inArray(item.institution, _institution) > -1;
}
if(_level.length) {
l = jQuery.inArray(item.level, _level) > -1;
}
if(_faculty.length) {
f = arrayIntersect(item.faculty, _faculty).length > 0;
}
return !!(i && l && f);
});
}
function getLevels(level, faculty) {
var colours = getColours(null, level, faculty);
var institutions = jQuery.map(colours, function(colour) { return colour.institution; });
institutions.sort(asc);
return arrayUnique(institutions);
}
function getUniversities(institution, faculty) {
var colours = getColours(institution, null, faculty);
var levels = jQuery.map(colours, function(colour) { return colour.level; });
levels.sort(asc);
return arrayUnique(levels);
}
function getFaculties(institution, level) {
var colours = getColours(institution, level, null);
var faculties = [];
jQuery.each(colours, function(index, item) {
faculties = arrayUnique(faculties.concat(item.faculty));
});
faculties.sort(asc);
return faculties;
}
function arrayUnique(array) {
var a = array.concat();
for(var i=0; i<a.length; ++i) {
for(var j=i+1; j<a.length; ++j) {
if(a[i] === a[j])
a.splice(j--, 1);
}
}
return a;
}
function asc(a, b) {
return a - b;
}
jQuery.mockjax({
url: ajaxurl,
contentType: 'application/json; charset=utf-8',
responseTime: 1000,
response: function(settings) {
this.responseText = JSON.stringify(getLevels(settings.data.level, settings.data.faculty));
}
});
jQuery.mockjax({
url: '/api/levels',
contentType: 'application/json; charset=utf-8',
responseTime: 1000,
response: function(settings) {
this.responseText = JSON.stringify(getUniversities(settings.data.institution, settings.data.faculty));
}
});
jQuery.mockjax({
url: '/api/faculties',
contentType: 'application/json; charset=utf-8',
responseTime: 1000,
response: function(settings) {
this.responseText = JSON.stringify(getFaculties(settings.data.institution, settings.data.level));
}
});
jQuery.mockjax({
url: '/api/colours',
contentType: 'application/json; charset=utf-8',
responseTime: 1000,
response: function(settings){
this.responseText = JSON.stringify(getColours(settings.data.institution, settings.data.level, settings.data.faculty));
}
});
Admin-Ajax.php
Response received from admin-ajax.php
Extra Notes
I have been stuck for a while trying to figure out how I can replace the Mockjax calls with the ajax calls from the server but I have not managed to understand all the technologies utilized fully.
Sincerely thank you, to whoever takes their time to help me guide me into the right direction. Your help is greatly appreciated at this point.