使用 AJAX 的动态级联下拉列表
Dynamic Cascading Dropdown using AJAX
Objective:
基于找到的示例 here。使用 ajax 调用在 getData()
函数中解析的数据填充相关下拉列表。目前我的示例正在处理 ajax-mocks.js
文件中的静态数据,但我无法理解如何将数据正确解析到下拉列表中,以及如何填充其他下拉列表,就像之前使用示例 mockjax 数据调用。
资源:
KnockoutJS - Loading/Saving Json Data
functions.php
呈现 HTML 到 woocommerce 前端产品页面
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-系统-public.php
从数据库中获取数据并将其处理为正确的格式
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();
}
自定义-dropdown.js
构建依赖级联下拉菜单
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
一些模拟ajax调用的mockjax数据
// 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
收到管理员的回复-ajax.php
补充说明
我已经被困了一段时间,试图弄清楚如何用来自服务器的 ajax 调用替换 Mockjax 调用,但我还没有完全理解所有使用的技术。
衷心感谢您花时间帮助我引导我走向正确方向的人。此时非常感谢您的帮助。
您的问题混合了 PHP、jQuery、knockout 和 许多 行代码。我冒昧地提取了一个核心问题,并写出了该部分问题的答案。
如何使用 knockout 创建基于异步数据的嵌套下拉列表
抽象的需求
您的系统(我认为)的工作方式是:
- 从服务器加载集合 A 和集合 D
- 需要从集合 A 中进行选择以从服务器检索集合 B,
- 需要从集合 B 中进行选择以从服务器检索集合 C,
- 当集合A,B 和 C中的选择时,过滤D
的列表
淘汰赛特征
在 knockout 中,您可以使用三个特征创建此依赖链:
observableArray
存储每个集合的服务器响应
subscribe
选择更改后触发新请求
pureComputed
根据多个数据源和选择自动过滤对象列表
流程顺序
在下面的例子中,我展示了如何在典型的淘汰模式中实现这一点:
- 加载
institutions
和 colours
异步。
- 当
institutions
加载时,knockout 在 <select>
中呈现它们
- 所选值绑定到
selection.institution
- 当这个值改变时,加载
faculties
异步
- 同样加载
levels
- 选择A
level
时,匹配所有三个 的过滤器colours
knockout 的依赖管理的美妙之处在于您可以随时更新这些列表中的任何一个,UI 将正确呈现。例如。您可以在做出三个选择后更新您的 colours
来源,列表将刷新。
例子
请注意,我使用了您代码段中的一些随机数据,因此对于许多组合,没有 colours
可用。此外,该示例包含您可能需要为旧版浏览器转换的 es6 功能。
const App = function() {
// The data sources
this.institutions = ko.observableArray([]);
this.faculties = ko.observableArray([]);
this.levels = ko.observableArray([]);
const colours = ko.observableArray([]);
// The selections made in the UI
this.selected = {
institution: ko.observable(null),
faculty: ko.observable(null),
level: ko.observable(null)
};
// The filter logic
this.availableColours = ko.pureComputed(() => {
if (colours().length === 0 ||
this.selected.institution() === null ||
this.selected.faculty() === null ||
this.selected.level() === null) {
return [];
}
const inst = this.selected.institution();
const fac = this.selected.faculty();
const lvl = this.selected.level();
return colours()
.filter(c =>
c.institution === inst &&
c.faculty.includes(fac) &&
c.level === lvl
);
}).extend({"deferred": true});
// Loading the data:
// 1. always load institutions & colours
mockAsync(getInstitutions)
.then(this.institutions);
mockAsync(getColours)
.then(colours);
// 2. load faculties after instution
this.selected.institution.subscribe(
selection => {
this.faculties([]);
/* do something with inst. in get URL */
mockAsync(getFaculties)
.then(this.faculties)
}
);
// 3. load levels after faculty
this.selected.faculty.subscribe(
selection => {
this.levels([]);
/* do something with inst. in get URL */
mockAsync(getLevels)
.then(this.levels)
}
);
}
ko.applyBindings(new App());
function mockAsync(fn) {
let _cb = () => {};
setTimeout(() => _cb(fn()), 200 + Math.random() * 300);
return {
then: cb => _cb = cb
}
};
function getLevels() { return ["Doctorate", "Bachelors", "Masters"]; };
function getInstitutions() { return [1, 2, 3]; };
function getFaculties(){ return [8, 16, 32, 64]; };
function getColours() { return [{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"}]; };
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<select data-bind="options: institutions,
optionsCaption: 'Select an institution',
value: selected.institution"></select>
<select data-bind="options: faculties,
optionsCaption: 'Select a faculty',
value: selected.faculty,
disable: !selected.institution()"></select>
<select data-bind="options: levels,
optionsCaption: 'Select a level',
value: selected.level,
disable: !selected.faculty()"></select>
<h3>Available colours:</h3>
<ul data-bind="foreach: availableColours">
<li data-bind="text: colour"></li>
</ul>
Objective:
基于找到的示例 here。使用 ajax 调用在 getData()
函数中解析的数据填充相关下拉列表。目前我的示例正在处理 ajax-mocks.js
文件中的静态数据,但我无法理解如何将数据正确解析到下拉列表中,以及如何填充其他下拉列表,就像之前使用示例 mockjax 数据调用。
资源:
KnockoutJS - Loading/Saving Json Data
functions.php
呈现 HTML 到 woocommerce 前端产品页面
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-系统-public.php
从数据库中获取数据并将其处理为正确的格式
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();
}
自定义-dropdown.js
构建依赖级联下拉菜单
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
一些模拟ajax调用的mockjax数据
// 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
收到管理员的回复-ajax.php
补充说明
我已经被困了一段时间,试图弄清楚如何用来自服务器的 ajax 调用替换 Mockjax 调用,但我还没有完全理解所有使用的技术。
衷心感谢您花时间帮助我引导我走向正确方向的人。此时非常感谢您的帮助。
您的问题混合了 PHP、jQuery、knockout 和 许多 行代码。我冒昧地提取了一个核心问题,并写出了该部分问题的答案。
如何使用 knockout 创建基于异步数据的嵌套下拉列表
抽象的需求
您的系统(我认为)的工作方式是:
- 从服务器加载集合 A 和集合 D
- 需要从集合 A 中进行选择以从服务器检索集合 B,
- 需要从集合 B 中进行选择以从服务器检索集合 C,
- 当集合A,B 和 C中的选择时,过滤D 的列表
淘汰赛特征
在 knockout 中,您可以使用三个特征创建此依赖链:
observableArray
存储每个集合的服务器响应subscribe
选择更改后触发新请求pureComputed
根据多个数据源和选择自动过滤对象列表
流程顺序
在下面的例子中,我展示了如何在典型的淘汰模式中实现这一点:
- 加载
institutions
和colours
异步。 - 当
institutions
加载时,knockout 在<select>
中呈现它们
- 所选值绑定到
selection.institution
- 当这个值改变时,加载
faculties
异步 - 同样加载
levels
- 选择A
level
时,匹配所有三个 的过滤器
colours
knockout 的依赖管理的美妙之处在于您可以随时更新这些列表中的任何一个,UI 将正确呈现。例如。您可以在做出三个选择后更新您的 colours
来源,列表将刷新。
例子
请注意,我使用了您代码段中的一些随机数据,因此对于许多组合,没有 colours
可用。此外,该示例包含您可能需要为旧版浏览器转换的 es6 功能。
const App = function() {
// The data sources
this.institutions = ko.observableArray([]);
this.faculties = ko.observableArray([]);
this.levels = ko.observableArray([]);
const colours = ko.observableArray([]);
// The selections made in the UI
this.selected = {
institution: ko.observable(null),
faculty: ko.observable(null),
level: ko.observable(null)
};
// The filter logic
this.availableColours = ko.pureComputed(() => {
if (colours().length === 0 ||
this.selected.institution() === null ||
this.selected.faculty() === null ||
this.selected.level() === null) {
return [];
}
const inst = this.selected.institution();
const fac = this.selected.faculty();
const lvl = this.selected.level();
return colours()
.filter(c =>
c.institution === inst &&
c.faculty.includes(fac) &&
c.level === lvl
);
}).extend({"deferred": true});
// Loading the data:
// 1. always load institutions & colours
mockAsync(getInstitutions)
.then(this.institutions);
mockAsync(getColours)
.then(colours);
// 2. load faculties after instution
this.selected.institution.subscribe(
selection => {
this.faculties([]);
/* do something with inst. in get URL */
mockAsync(getFaculties)
.then(this.faculties)
}
);
// 3. load levels after faculty
this.selected.faculty.subscribe(
selection => {
this.levels([]);
/* do something with inst. in get URL */
mockAsync(getLevels)
.then(this.levels)
}
);
}
ko.applyBindings(new App());
function mockAsync(fn) {
let _cb = () => {};
setTimeout(() => _cb(fn()), 200 + Math.random() * 300);
return {
then: cb => _cb = cb
}
};
function getLevels() { return ["Doctorate", "Bachelors", "Masters"]; };
function getInstitutions() { return [1, 2, 3]; };
function getFaculties(){ return [8, 16, 32, 64]; };
function getColours() { return [{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"}]; };
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<select data-bind="options: institutions,
optionsCaption: 'Select an institution',
value: selected.institution"></select>
<select data-bind="options: faculties,
optionsCaption: 'Select a faculty',
value: selected.faculty,
disable: !selected.institution()"></select>
<select data-bind="options: levels,
optionsCaption: 'Select a level',
value: selected.level,
disable: !selected.faculty()"></select>
<h3>Available colours:</h3>
<ul data-bind="foreach: availableColours">
<li data-bind="text: colour"></li>
</ul>