使用淘汰赛下拉

Posted

技术标签:

【中文标题】使用淘汰赛下拉【英文标题】:Drop down using knockout 【发布时间】:2015-06-11 12:11:34 【问题描述】:

目前我正在制作一个非常基本的时间表。 所以我目前拥有的是一个点击添加员工的按钮,它会为他们生成一周的时间。我希望发生的是员工姓名输入是一个下拉列表,但我不知道如何继续,这是我到目前为止所拥有的 小提琴 http://jsfiddle.net/grahamwalsh/1p3nnkyg/

html

<div class='timesheet'> 

<form action='/someServerSideHandler'>
    <p>You have asked for <span data-bind='text: employees().length'>&nbsp;</span> employee(s)</p>
    <table data-bind='visible: employees().length > 0'>
        <thead>
            <tr>
                <th>Employee Name</th>
                <th>Monday</th>
                <th>Tuesday</th>
                <th>Wednesday</th>
                <th>Thursday</th>
                <th>Friday</th>
                <th>Saturday</th>
                <th>Sunday</th>
                <th />
            </tr>
        </thead>
        <tbody data-bind='foreach: employees'>
            <tr>
                <td><input class='required' data-bind='value: name, uniqueName: true' /></td>
                <td><input class='required number' data-bind='value: hours, uniqueName: true' /></td>

删除

    <button data-bind='click: addEmployee'>Add Employee</button>
    <button data-bind='enable: employees().length > 0' type='submit'>Submit</button>
</form>

淘汰赛

var EmployeeModel = function(employees) 
var self = this;
self.employees = ko.observableArray(employees);

self.addEmployee = function() 
    self.employees.push(
        Name: "",
        Monday: "",
        Tuesday:"",
        Wednesday:"",
        Thursday:"",
        Friday:"",
        Saturday:"",
        Sunday:""
    );
;

self.removeEmployee = function(employee) 
    self.employees.remove(employee);
;

self.save = function(form) 
    alert("Could now transmit to server: " + ko.utils.stringifyJson(self.employees));

;
;

var viewModel = new EmployeeModel([
 ]);
 ko.applyBindings(viewModel);

 $("form").validate( submitHandler: viewModel.save );


body  font-family: arial; font-size: 14px; 

 .timesheet  padding: 1em; background-color: #EEEEDD; border: 1px solid #CCC; max-width: 655px; 
 .timesheet input  font-family: Arial; 
 .timesheet b  font-weight: bold; 
 .timesheet p  margin-top: 0.9em; margin-bottom: 0.9em; 
 .timesheet select[multiple]  width: 100%; height: 8em; 
 .timesheet h2  margin-top: 0.4em; font-weight: bold; font-size: 1.2em;     

.timesheet table, .liveExample td, .liveExample th  padding: 0.2em; border-width: 0; 
.timesheet td input  width: 13em; 
 tr  vertical-align: top; 
 .timesheet input.error  border: 1px solid red; background-color: #FDC; 
 .timesheet label.error  display: block; color: Red; font-size: 0.8em;  
 .timesheet th  font-weight: bold; 

  li  list-style-type: disc; margin-left: 20px; 

【问题讨论】:

类似 jsfiddle.net/1p3nnkyg/6 的东西。欢呼 @Liz 顺便说一句 - 我只是注意到到目前为止您还没有接受任何问题的答案。 It would be great if you could do so,这样您的问题就不会再显示为“未回答”;它使其他人更容易区分谁仍然需要帮助,谁不需要。谢谢! 嗨,对不起,我一定会这样做,我该如何接受? 谢谢!单击您希望接受的答案分数下方的小复选标记。 Here is a screenshot。此外,当您编写 cmets 时,您可以将某人的姓名包含在 @ 符号中,例如@janfoeh。然后,该人会收到您已回复他们的通知 - 否则他们可能会错过您的回复。干杯! 【参考方案1】:

如果我正确理解您的问题,您希望您的用户从员工列表中选择一个或多个人。您的方法有几个问题,我正在努力纠正这些问题。

您将视图模型命名为 EmployeeModel,但您基本上还有另一个针对员工的临时数据模型:

self.employees.push(
    Name: "",
    Monday: "",
    Tuesday:"",
    Wednesday:"",
    Thursday:"",
    Friday:"",
    Saturday:"",
    Sunday:""
);

顺便说一句,这是行不通的,因为您忘记将属性设置为可观察的。如果将Name绑定到输入字段值,例如&lt;input data-bind="value: Name"&gt;,它只会将输入设置为Name的初始内容一次。之后,无论您更改可观察到的 Name 还是 &lt;input&gt; 值,都不会再发生任何事情。

所以让我们将您的视图模型重命名为ViewModel 并为Employee 创建一个专用数据模型:

var Employee = function Employee(name) 
    this.name      = ko.observable(name);
    this.monday    = ko.observable();
    this.tuesday   = ko.observable();
    this.wednesday = ko.observable();
    this.thursday  = ko.observable();
    this.friday    = ko.observable();
    this.saturday  = ko.observable();
    this.sunday    = ko.observable();
;

出于本演示的目的,我会将它们直接输入到视图模型中:

var viewModel = new ViewModel([
    new Employee('Jane'),
    new Employee('John'),
    new Employee('Alice'),
    new Employee('Bob')
]);

我们基本上有两个列表——

    用户可以从中选择的员工列表,以及 用户选择的员工

所以我们需要两个 observableArrays:

var ViewModel = function ViewModel(employees) 
    this.availableEmployees = ko.observableArray(employees);
    this.selectedEmployees  = ko.observableArray([]);
;

我会改变用户界面,让用户首先选择员工:

这样,我们可以使用只包含尚未添加的员工的动态选择,从而可以防止员工被添加两次。

这是我们的&lt;select&gt;

<!-- ko if: availableEmployees().length > 0 -->
    <select data-bind="value: employeeToBeAdded,
                       options: availableEmployees,
                       optionsText: 'name'">
    </select>
    <button data-bind='click: addEmployee'>Add Employee</button>
<!-- /ko -->

我们从所有availableEmployees 创建选项,并使用每个Employeename 属性作为选项标签文本。如果没有可用的,我们将隐藏所有内容。

employeeToBeAdded 是另一个 observable,持有当前在&lt;select&gt; 中选择的员工,单击“添加员工”时将添加该员工。

发生这种情况时,我们会从列表中获取选定的员工,将其添加到 selectedEmployees 并从 availableEmployees 中删除。对于removeEmployee,我们反其道而行之:

var ViewModel = function ViewModel(employees) 
    var self = this;

    this.availableEmployees = ko.observableArray(employees);
    this.selectedEmployees  = ko.observableArray([]);
    this.employeeToBeAdded  = ko.observable();

    this.addEmployee = function addEmployee() 
        var employee = self.employeeToBeAdded();
        self.employeeToBeAdded(null);
        self.selectedEmployees.push( employee );
        self.availableEmployees.remove( employee );        
    ;

    this.removeEmployee = function removeEmployee(employee) 
        self.availableEmployees.push(employee);
        self.selectedEmployees.remove(employee);
    ;
;

这是完整的、可运行的示例:

var Employee = function Employee(name) 
    this.name      = ko.observable(name);
    this.monday    = ko.observable();
    this.tuesday   = ko.observable();
    this.wednesday = ko.observable();
    this.thursday  = ko.observable();
    this.friday    = ko.observable();
    this.saturday  = ko.observable();
    this.sunday    = ko.observable();
;

var ViewModel = function ViewModel(employees) 
    var self = this;
    
    this.availableEmployees = ko.observableArray(employees);
    this.selectedEmployees  = ko.observableArray([]);
    this.employeeToBeAdded  = ko.observable();
    
    this.addEmployee = function() 
        var employee = self.employeeToBeAdded();
        self.employeeToBeAdded(null);
        self.selectedEmployees.push(employee);
        self.availableEmployees.remove(employee);        
    ;
 
    self.removeEmployee = function(employee) 
        self.availableEmployees.push(employee);
        self.selectedEmployees.remove(employee);
    ;
 
    self.save = function(form) 
        alert("Could now transmit to server: " + ko.utils.stringifyJson(self.employees));
       
    ;
;
 
var viewModel = new ViewModel([
    new Employee('Jane'),
    new Employee('John'),
    new Employee('Alice'),
    new Employee('Bob')
]);

ko.applyBindings(viewModel);
body  font-family: arial; font-size: 14px; 

.timesheet  padding: 1em; background-color: #EEEEDD; border: 1px solid #CCC; max-width: 655px; 
.timesheet input  font-family: Arial; 
.timesheet b  font-weight: bold; 
.timesheet p  margin-top: 0.9em; margin-bottom: 0.9em; 
.timesheet select[multiple]  width: 100%; height: 8em; 
.timesheet h2  margin-top: 0.4em; font-weight: bold; font-size: 1.2em; 

.timesheet table, .liveExample td, .liveExample th  padding: 0.2em; border-width: 0; 
.timesheet td input  width: 5em; 
tr  vertical-align: top; 
.timesheet input.error  border: 1px solid red; background-color: #FDC; 
.timesheet label.error  display: block; color: Red; font-size: 0.8em;  
.timesheet th  font-weight: bold; 

li  list-style-type: disc; margin-left: 20px; 

.debugging-output  padding: 2rem; 
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div class='timesheet'> 
    
    <form action='/someServerSideHandler'>
        <p>You have asked for <span data-bind='text: selectedEmployees().length'>&nbsp;</span> employee(s)</p>
        <table data-bind='visible: selectedEmployees().length > 0'>
            <thead>
                <tr>
                    <th>Employee Name</th>
                    <th>Monday</th>
                    <th>Tuesday</th>
                    <th>Wednesday</th>
                    <th>Thursday</th>
                    <th>Friday</th>
                    <th>Saturday</th>
                    <th>Sunday</th>
                    <th />
                </tr>
            </thead>
            <tbody data-bind='foreach: selectedEmployees'>
                <tr>
                    <td data-bind="text: name"></td>
                    <td><input class='required number' data-bind='value: monday, uniqueName: true' /></td>
                    <td><input class='required number' data-bind='value: tuesday, uniqueName: true' /></td>
                    <td><input class='required number' data-bind='value: wednesday, uniqueName: true' /></td>
                    <td><input class='required number' data-bind='value: thursday, uniqueName: true' /></td>
                    <td><input class='required number' data-bind='value: friday, uniqueName: true' /></td>
                    <td><input class='required number' data-bind='value: saturday, uniqueName: true' /></td>
                    <td><input class='required number' data-bind='value: sunday, uniqueName: true' /></td>
                    <td><button data-bind='click: $parent.removeEmployee'>Delete</button></td>
                </tr>
            </tbody>
        </table>
     
        <!-- ko if: availableEmployees().length > 0 -->
            <select data-bind="value: employeeToBeAdded, options: availableEmployees, optionsText: 'name'"></select>
            <button data-bind='click: addEmployee'>Add Employee</button>
        <!-- /ko -->
        <button data-bind='enable: selectedEmployees().length > 0' type='submit'>Submit</button>
    </form>
    
</div>

<ul class="debugging-output" data-bind="foreach: selectedEmployees">
  <li data-bind="text: ko.toJSON($data)"></li>
</ul>

【讨论】:

以上是关于使用淘汰赛下拉的主要内容,如果未能解决你的问题,请参考以下文章

剑道淘汰赛下拉列表更改事件未触发

如何使用淘汰赛js在两个控件之间建立关系

将项目列表转换为下拉列表淘汰js

淘汰赛确定下拉列表选择并将文本更新到数据库

编辑,删除和下拉显示正确的字段淘汰js

如何使用淘汰赛从复杂对象的选择选项中设置值?