这是我的观点;
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<SHP.Models.TrainingListEmployeesViewModel>" %>
<%@ Import Namespace="System.Web.Script.Serialization" %>
<%@ Import Namespace="SHP.Helpers" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Bulk Training
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<form class="employeeListEditor" data-bind="submit: save">
<fieldset>
<legend>Allocate or cancel training for the selected employees</legend>
<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 id="btnAdd" data-bind="click: addEmployee">Add</button><button data-bind="click: clearEmployee">Clear</button>
<div id="displayEmployees" style="margin-top:10px;" data-bind="visible: employees().length > 0">
<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: $parent.removeEmployee">Remove</a>
<input type="hidden" data-bind="value: SearchTextId"/>
</td>
<td><span data-bind="text: SearchText"></span></td>
</tr>
</tbody>
</table>
</div>
<div id="employeeCalendar">
<% if(Model.Cvm != null)
{%>
<% Html.RenderPartial("Calendar", Model.Cvm); %>
<div><span style="margin-top: 10px"></span></div>
<div style="margin-top:20px;">
<div style="display: inline; margin-right:20px; padding:5px;">
<%:Html.MakePopupForm<SHP.Controllers.LeaveController>(o => o.TrainingSingleDate(), refreshOnSuccess: true)%>
<%:Html.PopupFormActionLink<SHP.Controllers.LeaveController>(o => o.TrainingSingleDate(), "Add a single date")%>
</div>
</div>
<% if (TempData["SuccessMessage"].ToSafeString().Length > 0)
{%>
<p class="success" style="padding-top: 20px;"><%: TempData["SuccessMessage"].ToSafeString() %></p>
<% } %>
<% }%>
</div>
</fieldset>
</form>
<script type="text/javascript">
function Employee(id, text) {
var self = this;
self.SearchTextId = ko.observable(id);
self.SearchText = ko.observable(text);
}
$(document).ready(function () {
$('#SearchText').attr("data-bind", "value: autocompleteSearchText");
$('#SearchTextId').attr("data-bind", "value: autocompleteSearchTextId");
$("#TrainingName").attr("data-bind", "value: trainingName");
$("#TrainingDescription").attr("data-bind", "value: trainingDescription");
var initialData = <%= new JavaScriptSerializer().Serialize(Model) %>;
var autocompleteData = { "autocompleteSearchTextId": 0, "autocompleteSearchText": null };
function viewModel() {
var self = this;
self.employees = ko.observableArray(initialData.EmployeeList);
self.trainingName = ko.observable(initialData.TrainingName);
self.trainingDescription = ko.observable(initialData.TrainingDescription);
self.autocompleteSearchText = ko.observable(autocompleteData.autocompleteSearchText);
self.autocompleteSearchTextId = ko.observable(autocompleteData.autocompleteSearchTextId);
self.removeEmployee = function(employee) {
$("#btnAdd").after("<span class='error'>Please wait for calendar update ...</span>");
self.employees.remove(employee);
self.save();
};
self.clearEmployee = function() {
self.autocompleteSearchText('');
};
self.addEmployee = function() {
$("#btnAdd").after("<span class='error'>Please wait for calendar update ...</span>");
self.employees.push(new Employee(self.autocompleteSearchTextId(), self.autocompleteSearchText()));
self.autocompleteSearchText('');
self.save();
};
self.save = function() {
var list = ko.toJS(self.employees);
var name = ko.toJS(self.trainingName);
var description = ko.toJS(self.trainingDescription);
ko.utils.postJson(location.href, { employees: list, trainingName: name, trainingDescription: description });
};
}
ko.applyBindings(new viewModel());
});
</script>
</asp:Content>
您可能会注意到我在此视图中有一个弹出表单。另外,我想将employeeCalendar div中的所有代码放在部分视图中。由于弹出窗口,我必须确保在我的控制器中将我的 Post 方法重定向到我的 Get 方法,以便当弹出数据输入完成并取消此视图的日期时,我不会从窗口收到不需要的重新发送消息。做这些重定向的问题是我得到一个看起来不愉快的整页回发。所以我宁愿通过 Ajax 从局部视图中刷新我的 claendar。那么我该怎么做呢?这是我的控制器
[HttpGet]
[Authorize(Roles = "Administrator, Trainer, ManagerAccounts, ManagerIT")]
public ActionResult BulkTraining()
{
if (SessionObjects.Tlevm == null)
{
return this.View(new TrainingListEmployeesViewModel());
}
return this.View(new TrainingListEmployeesViewModel(
SessionObjects.Tlevm.EmployeeList,
SessionObjects.TrainingName,
SessionObjects.TrainingDescription));
}
[HttpPost]
[Authorize(Roles = "Administrator, Trainer, ManagerAccounts, ManagerIT")]
public ActionResult BulkTraining([FromJson] IEnumerable<ClientEmployeeSelector> employees, string trainingName, string trainingDescription)
{
// Items stored in Session used when saving the training dates for the employee
// via the popup window
SessionObjects.TrainingName = trainingName.JsonTrim();
SessionObjects.TrainingDescription = trainingDescription.JsonTrim();
SessionObjects.EmployeeIdList = employees.Select(x => x.SearchTextId).ToList();
SessionObjects.EmployeeNameList = SessionObjects.EmployeeIdList.Count > 0
? Employee.GetNameList(SessionObjects.EmployeeIdList)
: string.Empty;
SessionObjects.Tlevm = new TrainingListEmployeesViewModel(
employees.ToList(),
SessionObjects.TrainingName,
SessionObjects.TrainingDescription);
return this.RedirectToAction("BulkTraining");
}