使用击倒下拉

Drop down using knockout

目前我正在制作一个非常基本的时间表。 所以我目前拥有的是一个点击添加员工的按钮,它会为他们生成一个星期。我想要发生的是员工姓名输入是一个下拉列表,但我不确定如何继续,这是我到目前为止所拥有的 一个 fiddle 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; }

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

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

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

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

所以让我们将您的视图模型重命名为 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')
]);

我们基本上有两个列表 —

  1. 用户可以选择的员工列表,以及
  2. 用户select编
  3. 的员工

所以我们需要两个 observableArrays:

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

我会更改用户界面,让用户 select 首先成为员工:

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

这是我们的 <select>:

<!-- 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 属性 作为选项标签文本。如果 none 可用,我们将隐藏所有内容。

employeeToBeAdded 是另一个 observable,包含当前 selected 在 <select> 中的员工,单击 "Add Employee" 时将添加该员工。

发生这种情况时,我们从列表中获取 selected 员工,将其添加到 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>