0

我是第一次尝试 Knockout,我正在努力让它发挥作用。基本场景是我想使用自动完成将员工添加到列表中。我也希望能够删除。当用户满意时,他可以单击提交,这会将 id 列表发布到服务器,我将在该服务器上进入流程的下一部分。目前我正在尝试让添加的员工先工作。

我有一个服务器端视图模型类;

public class TrainingListEmployeesViewModel : BaseTrainingViewModel
{
    public TrainingListEmployeesViewModel()
    {
        this.EmployeeList = new List<int>();
        this.ClientEmployeeSelector = new ClientEmployeeSelector();
    }

    public TrainingListEmployeesViewModel(List<int> employeeList, string trainingName, string trainingDescription)
        : base(trainingName, trainingDescription)
    {
        this.EmployeeList = employeeList;
        var dates = new CalendarDates(Utility.GetToday(), Utility.GetToday().AddYears(1));
        this.Cvm = new CalendarViewModel(employeeList.ToList(), dates);
    }

    public List<int> EmployeeList { get; set; }

    public ClientEmployeeSelector ClientEmployeeSelector { get; set; }
}

}

控制器看起来像这样;

[HttpPost]
        [Authorize(Roles = "Administrator, Trainer, ManagerAccounts, ManagerIT")]
        [ValidateAntiForgeryToken]
        [ValidateOnlyIncomingValuesAttribute]
        public ActionResult Training(TrainingViewModel tvm)
        {
            SessionObjects.TrainingName = tvm.TrainingName;
            SessionObjects.TrainingDescription = tvm.TrainingDescription;
            return this.RedirectToAction("Training", new { employeeId = tvm.EmployeeSelector.SearchTextId });
        }

        [HttpGet]
        [Authorize(Roles = "Administrator, Trainer, ManagerAccounts, ManagerIT")]
        public ActionResult BulkTraining()
        {
            return this.View(new TrainingListEmployeesViewModel());
        }

视图看起来像这样;

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<SHP.Models.TrainingListEmployeesViewModel>" %>
<%@ Import Namespace="System.Web.Script.Serialization" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Bulk Training
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<form class="employeeListEditor">
    <h3>Allocate or cancel training for the selected employees</h3>
    <table>
        <tr>
            <td style="text-align: right;">Course Name</td>
            <td><%: Html.EditorFor(model => model.TrainingName) %></td>
        </tr>
        <tr>
            <td style="text-align: right;">Description (optional)</td>
            <td><%: Html.TextAreaFor(
               model => model.TrainingDescription, new { maxlength = "255", style = "width:400px;height:100px;" }) %></td>
        </tr>
    </table>
    <%: Html.EditorFor(model => model.ClientEmployeeSelector) %>
    <button data-bind="click: addEmployee">Add</button>
    <div id="displayEmployees" style="margin-top:10px;display: block">
        <table id="employeeDataTable" class="groupBorder">
            <thead>
                <tr>
                    <th></th>
                    <th>Employee</th>
                </tr>
            </thead>
            <tbody data-bind="foreach: employees">
                <tr>
                    <td>
                        <a href="#" data-bind="click: function() { viewModel.removeEmployee($data) }">Remove</a>
                        <input type="hidden" data-bind="value: searchTextId"/>
                    </td>
                    <td><span data-bind="value: searchText"></span></td>
                </tr>               
            </tbody>
        </table>
    </div>
</form>

    <script type="text/javascript">
        function Employee(id, text) {
            var self = this;
            self.searchId = id;
            self.searchText = text;
        }

        var initialData = <%= new JavaScriptSerializer().Serialize(Model) %>;
        function ViewModel() {
            var self = this;
            self.employees = ko.observableArray(initialData.EmployeeList);
            self.searchText = ko.observable(initialData.SearchText);
            self.searchTextId = ko.observable(initialData.SearchTextId);
            self.removeEmployee = function(employee) {
                this.employees.remove(employee);
            };
            self.addEmployee = function() {
                alert(self.searchText);
                this.employees.push(new Employee(self.searchTextId, self.searchText));
            };
            self.save = function() {
                ko.utils.postJson(location.href, { employees: self.employees });
            };
        }
        ko.applyBindings(new ViewModel());
    </script>
</asp:Content>

编辑器模板看起来像包含自动完成的 ClientEmployeeSelector;

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<SHP.Models.ClientEmployeeSelector>" %>

        <table class="groupBorder">
            <tr>
                <th colspan="2">Enter 2 or more characters for "<%: Html.LabelFor(model => model.SearchText)%>" and select from the list.</th>
            </tr>
            <tr>
                <td><%: Html.LabelFor(model => model.SearchText)%></td>
                <td><%: Html.AutocompleteFor(model => model.SearchText, controller: "Payroll",
                                            minLength: 2, maxResults: 10,
                                            htmlAttributes: new { style = "color:purple; width:500px;" })%>
                                <%: Html.HiddenFor(model => model.SearchTextId)%>
                                <%: Html.HiddenFor(model => model.SearchText)%>
                </td>
            </tr>
        </table>

我收到一条错误消息;searchTextId 未定义。当我查看 IE 开发人员工具中发生的情况时,searchTextId 存在正常,但无法找到它的值。那么我怎样才能让它工作呢?我怀疑我需要做一些改变。

4

1 回答 1

1

在我看来,您绑定了错误的属性。如果要显示包含员工的表格,则应在foreach绑定中使用员工的属性。此外,最好在绑定中使用$parentor$root对象而不是使用viewModel对象:

    <tbody data-bind="foreach: employees">
        <tr>
            <td>
                <a href="#" data-bind="click: $parent.removeEmployee">Remove</a>
                <input type="hidden" data-bind="value: searchId"/>
            </td>
            <td><span data-bind="text: searchText"></span></td>
        </tr>               
    </tbody>

这是工作小提琴:http: //jsfiddle.net/vyshniakov/yXvDB/2/

但是如果你真的想searchTextId在员工表中显示视图模型的属性,你应该使用$parent对象:

<input type="hidden" data-bind="value: $parent.searchTextId"/>
于 2012-10-15T14:11:42.170 回答