javascript - KnockoutJS - 根据另一个菜单中的选择设置选择菜单

标签 javascript html knockout.js

我有两个<select>菜单和文本框。当选择第一个菜单中的选项时,它应该更新文本框中的值,并且还应该在第二个选择菜单中设置所选选项。

文本框正确更新。

但是,第二个选择菜单未更新。

ParentID第一个菜单中的值应用于指定 TaskID第二个菜单的值。 ParentID值是对 TaskID 的 FK 引用在同一张表中。

例如,在下面,如果在第一个菜单中选择“ManualItems”,则“Positions”应成为在第二个菜单中选择的值。

var viewModel = function(data) {
    var self = this;
   
    // variables
    self.currentTask = ko.observable();
    self.selectedParentTask = ko.observable();
    self.taskDescription = ko.observable("");
   
    self.tasks = ko.observableArray([
        {TaskID: 1, TaskName: "ManualItems", TaskDescription: "Manual Rec", ParentID: 4, ParentName: "Positions"},
        {TaskID: 2, TaskName: "Trades", TaskDescription: "Trades Data", ParentID: null, ParentName: null},
        {TaskID: 3, TaskName: "File-In", TaskDescription: "File Detail", ParentID: 2, ParentName: "Trades"},
        {TaskID: 4, TaskName: "Positions", TaskDescription: "Positions Overview", ParentID: null, ParentName: null}
    ]);
    
    self.parentTasks = ko.observableArray([
        {TaskID: 1, TaskName: "ManualItems", TaskDescription: "Manual Rec", ParentID: 4, ParentName: "Positions"},
        {TaskID: 2, TaskName: "Trades", TaskDescription: "Trades Data", ParentID: null, ParentName: null},
        {TaskID: 3, TaskName: "File-In", TaskDescription: "File Detail", ParentID: 2, ParentName: "Trades"},
        {TaskID: 4, TaskName: "Positions", TaskDescription: "Positions Overview", ParentID: null, ParentName: null}
    ]);
    
    /*
    self.currentTask.subscribe(function(newValue){
      self.selectedParentTask(newValue);
    });
    */
    
    self.EditTask = function () {
        // populate all fields with selected task
        self.taskDescription(self.currentTask().TaskDescription);
        self.selectedParentTask(self.currentTask()); // set parent task to the ParentID value of currentTask
    };
};

ko.applyBindings(new viewModel());
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<div class="form-group">
    <label for="taskName">Edit Existing Task</label>
    <select class="form-control" id="taskNameSelect" data-bind="
        options: tasks,
        optionsText: 'TaskName',
        value: currentTask,
        event: {change: $root.EditTask},
        optionsCaption: 'Select Task...'
    "></select>
</div>
<div class="form-group">
    <label for="taskParent">Select Parent Task</label>
    <select class="form-control" id="taskParent" data-bind="
        options: parentTasks,
        optionsText: 'TaskName',
        value: selectedParentTask,
        optionsCaption: 'Select Parent Task...'
    "></select>
</div>
<div class="form-group">
    <label for="taskDescription">Task Description</label>
    <textarea class="form-control" id="taskDescription" rows="3" placeholder="Enter Task Description" data-bind="value: taskDescription"></textarea>
</div>

这是 JSFiddle 中的代码也是如此。

最佳答案

作为一般规则,避免在 knockout 中设置 DOM 事件处理程序。大多数时候,通过使用订阅,您可以用更少的代码和更少的歧义来完成同样的任务。

在这种情况下,您希望通过查找与其匹配的父任务来对 currentTask 中的更改使用react。

ko.utils.arrayFirst() 是一个方便的 utility function从数组中取出符合特定条件的第一个元素。 (现在您也可以使用 Array#find 达到相同的效果。)

所以,我们得到:

self.currentTask.subscribe(function (task) {
    var matchingParentTask = ko.utils.arrayFirst(self.parentTasks(), function (parent) {
        return parent.TaskName === task.ParentName;
    });
    self.parentTask(matchingParentTask);
    self.taskDescription(task.TaskDescription);
});

在上下文中:

var viewModel = function(data) {
    var self = this;
   
    // variables
    self.currentTask = ko.observable();
    self.parentTask = ko.observable();
    self.taskDescription = ko.observable();
   
    self.tasks = ko.observableArray([
        {TaskID: 1, TaskName: "ManualItems", TaskDescription: "Manual Rec", ParentID: 4, ParentName: "Positions"},
        {TaskID: 2, TaskName: "Trades", TaskDescription: "Trades Data", ParentID: null, ParentName: null},
        {TaskID: 3, TaskName: "File-In", TaskDescription: "File Detail", ParentID: 2, ParentName: "Trades"},
        {TaskID: 4, TaskName: "Positions", TaskDescription: "Positions Overview", ParentID: null, ParentName: null}
    ]);
    
    self.parentTasks = ko.observableArray([
        {TaskID: 1, TaskName: "ManualItems", TaskDescription: "Manual Rec", ParentID: 4, ParentName: "Positions"},
        {TaskID: 2, TaskName: "Trades", TaskDescription: "Trades Data", ParentID: null, ParentName: null},
        {TaskID: 3, TaskName: "File-In", TaskDescription: "File Detail", ParentID: 2, ParentName: "Trades"},
        {TaskID: 4, TaskName: "Positions", TaskDescription: "Positions Overview", ParentID: null, ParentName: null}
    ]);
    
    self.currentTask.subscribe(function (task) {
        var matchingParentTask = ko.utils.arrayFirst(self.parentTasks(), function (parent) {
            return parent.TaskName === task.ParentName;
        });
        self.parentTask(matchingParentTask);
        self.taskDescription(task.TaskDescription);
    });
};

ko.applyBindings(new viewModel());
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<div class="form-group">
    <label for="taskName">Edit Existing Task</label>
    <select class="form-control" id="taskNameSelect" data-bind="
        value: currentTask,
        options: tasks,
        optionsText: 'TaskName',
        optionsCaption: 'Select Task...'
    "></select>
</div>
<div class="form-group">
    <label for="taskParent">Select Parent Task</label>
    <select class="form-control" id="taskParent" data-bind="
        value: parentTask,
        options: parentTasks,
        optionsText: 'TaskName',
        optionsCaption: 'Select Parent Task...'
    "></select>
</div>
<div class="form-group">
    <label for="taskDescription">Task Description</label>
    <textarea class="form-control" id="taskDescription" rows="3" placeholder="Enter Task Description" data-bind="value: taskDescription"></textarea>
</div>

关于javascript - KnockoutJS - 根据另一个菜单中的选择设置选择菜单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44280687/

相关文章:

javascript - 带有 knockout.JS 的异步 getJSON

knockout.js - Knockoutjs - 使用映射插件订阅

javascript - 为什么我在 Angular 页面中收到 "service is not defined"错误消息?

javascript - 在javascript中动态生成行?

javascript - 无法编辑 HTML 文本输入中的最后两个字符

html - 什么是代表 "loading . . ."的良好 CSS 样式?

html - 下拉菜单,子项自动出现

javascript - Knockout - 变量值包含函数体

javascript - ajax 请求后将数据传递给变量

javascript - 如何调试Javascript进程和动画?