我有一个这样的视图模型:
var Jobs = [
{ "Id": "J01", "Value": "description1" },
{ "Id": "J02", "Value": "description2" },
{ "Id": "J03", "Value": "description3" }
]
var Tasks = []
var Line = function (obj) {
var self = this;
self.Job = ko.observable(obj.JobId)
self.Task = ko.observable(obj.TaskId)
self.Job.subscribe(function () {
/*
Here i want to run ajax and fetch tasks for that
job and i assume this should work for related tasks dropdown only
*/
});
}
function ViewModel() {
var self = this
self.Timesheet = ko.observable()
self.LoadData = function () {
var data = {
"timesheet": {
"ApprovalStatus": 1,
"Description": "Timesheet",
"PeriodFrom": "2013-09-01",
"PeriodTo": "2013-09-15",
"RecId": "1",
"Lines": [{
"DestinationRecId": "D01",
"LaborCategoryRecId": "C01",
"PayTypeRecId": "PAY-01",
"ProjectRecId": "J01",
"ProjectWBSRecId": "J01-T01",
"RecId": "1"
}, {
"DestinationRecId": "D02",
"LaborCategoryRecId": "C01",
"PayTypeRecId": "PAY-02",
"ProjectRecId": "J02",
"ProjectWBSRecId": "J02-T01",
"RecId": "2"
}
}
}
self.Timesheet(data.timesheet)
for (var i = 0; i < data.timesheet.Lines.length; i++) {
var line = self.Timesheet().Lines[i]
var obj = {
JobId : line.ProjectRecId,
TaskId : line.ProjectWBSRecId
}
/* Here i am adding property SelectedItem and
* in it assigning a child object
*/
self.Timesheet().Lines[i].SelectedItem = new Line(obj)
console.log(self.Timesheet().Lines[i])
}
}
self.LoadData()
}
以下是相应的观点:
<table>
<thead>
<tr>
<th>Job </th>
<th>Job WBS</th>
</tr>
</thead>
<tbody id="lines" data-bind="foreach:Timesheet().Lines">
<tr>
<td>
<select
data-bind="
options: Jobs,
optionsText: 'Value',
optionsValue: 'Id',
optionsCaption: 'Select Job',
value : $data.ProjectRecId
"
class="m-wrap">
<!-- $data.ProjectRecId $data.SelectedItem.Job-->
</select>
</td>
<td data-bind="with: Jobs">
<select
data-bind="
options: Tasks,
optionsText: 'Value',
optionsValue: 'Id',
value : $data.ProjectWBSRecId,
optionsCaption: 'Select Task'
"
class="m-wrap">
</select>
</td>
</tr>
</tbody>
</table>
问题在于,当我使用$data.SelectedItem.Job
时,它表示SelectedItem
未定义
使用$data.ProjectRecId
可以正常工作。目标是实现“Knockout Dependent Dropdowns Handling”之类的内容。
我想单独处理下拉菜单,但我没有做到这一点。
输出:
答案 0 :(得分:1)
基本上我使用Note 3: Using “as” to give an alias to “foreach” items来允许直接连接到self.Timesheet().Lines[i].SelectedItem
,这反过来又允许我为Job
和Task
使用每个相应value binding
的观察值}}
通过使用函数调用替换“任务”组合框的options
绑定,您可以根据该行的选定“作业”加载自定义值。如果self.Task = ko.observable(obj.TaskId)
设置的原始值存在于函数返回的选项中,则将选择/显示该值。
实现与您提供的教程不完全相同,因为该示例中使用的viewmodel的结构与您提供的data
对象的结构完全不同。我将Jobs
移动到他们自己的属性中,并假设您可以在遍历行时单独查询/构建该数据。否则,数据需要以这样的方式构造,即它将1个Job与多个任务相关联,而不是将Job / Task对彼此相关联。如果要更改数据结构,那么可以实现与所提供的示例更紧密相关的实现。
<强> HTML 强>:
<button data-bind="click:printLines">Print Lines</button>
<table>
<thead>
<tr>
<th>Job </th>
<th>Job WBS</th>
</tr>
</thead>
<tbody id="lines" data-bind="foreach: {data: Timesheet().Lines, as: 'line'}">
<tr>
<td>
<select
data-bind="
options: $root.Jobs,
optionsText: 'Value',
optionsValue: 'Id',
optionsCaption: 'Select Job',
value : line.SelectedItem.Job
"
class="m-wrap">
<!-- $data.ProjectRecId $data.SelectedItem.Job-->
</select>
</td>
<td data-bind="with: line.SelectedItem.Job">
<select
data-bind="
options: $root.getAvailableTasks(line.SelectedItem.Job),
optionsText: 'Value',
optionsValue: 'Id',
value : line.SelectedItem.Task,
optionsCaption: 'Select Task'
"
class="m-wrap">
</select>
</td>
</tr>
</tbody>
</table>
<强>的Javascript 强>:
var Line = function (obj) {
var self = this;
self.Job = ko.observable(obj.JobId)
self.Task = ko.observable(obj.TaskId)
self.Job.subscribe(function () {
/*
Here i want to run ajax and fetch tasks for that
job and i assume this should work for related tasks dropdown only
*/
});
}
function ViewModel() {
var self = this;
self.Jobs = ko.observableArray([
{ "Id": "J01", "Value": "description1" },
{ "Id": "J02", "Value": "description2" },
{ "Id": "J03", "Value": "description3" }
]);
self.formattedData = ko.observableArray([]);
self.Timesheet = ko.observable()
self.LoadData = function () {
var data = {
"timesheet": {
"ApprovalStatus": 1,
"Description": "Timesheet",
"PeriodFrom": "2013-09-01",
"PeriodTo": "2013-09-15",
"RecId": "1",
"Lines": [{
"DestinationRecId": "D01",
"LaborCategoryRecId": "C01",
"PayTypeRecId": "PAY-01",
"ProjectRecId": "J01",
"ProjectWBSRecId": "J01-T01",
"RecId": "1"
}, {
"DestinationRecId": "D02",
"LaborCategoryRecId": "C01",
"PayTypeRecId": "PAY-02",
"ProjectRecId": "J02",
"ProjectWBSRecId": "J02-T01",
"RecId": "2"
}]
}
}
self.Timesheet(data.timesheet)
for (var i = 0; i < data.timesheet.Lines.length; i++) {
var line = self.Timesheet().Lines[i]
var obj = {
JobId : line.ProjectRecId,
TaskId : line.ProjectWBSRecId
}
/* Here i am adding property SelectedItem and
* in it assigning a child object
*/
line.SelectedItem = new Line(obj);
}
}
self.printLines = function() {
for (var i = 0; i < self.Timesheet().Lines.length; i++) {
var selectedItem = self.Timesheet().Lines[i].SelectedItem;
console.log('Job: ' + selectedItem.Job() + " Task: " + selectedItem.Task());
}
}
self.getAvailableTasks=function(selectedJob) {
//your ajax would move here
if("J01" == selectedJob()){
return ko.observableArray([{"Id": "J01-T01", "Value": "TaskJ01-T01Value"},
{"Id": "J01Task02", "Value": "Task02Value"}]);
}
else {
return ko.observableArray([{"Id": "DefaultTask01", "Value": "Task01Value"},
{"Id": "DefaultTask02", "Value": "Task02Value"}]);
}
}
self.LoadData()
}
ko.applyBindings(new ViewModel())