0

我有一个这样的视图模型:

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 ”之类的东西。

我想单独处理下拉菜单,但我失败了。

输出:

在此处输入图像描述

4

1 回答 1

1

看看我的实现

本质上,我使用 了注 3:使用“as”为“foreach”项目提供别名,以允许直接连接到该项目self.Timesheet().Lines[i].SelectedItem,这反过来又允许我为每个相应的Job和使用可观察对象。Taskvalue binding

通过用options函数调用替换“任务”组合框的绑定,您可以根据为该行选择的“作业”加载自定义值。如果函数返回的选项中存在由设置的原始值self.Task = ko.observable(obj.TaskId),那么它将被选中/显示。

该实现与您提供的教程并不完全相同,因为该示例中使用的视图data模型的结构与您提供的对象完全不同。我搬进Jobs了他们自己的财产,并假设您可以在遍历这些行时单独查询/构建该数据。否则,数据的结构需要将 1 个作业与多个任务相关联,而不是将作业/任务对并排在一起。如果要更改数据结构,则可以实现与提供的示例更紧密相关的实现。

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())
于 2013-10-25T05:15:33.600 回答