我正在尝试创建一个包含子行(每行一个子节点)的表作为详细信息部分。在此详细信息部分中,用户将能够查看日志历史记录,还可以输入特定日志。输入新日志并单击“添加”按钮后,日志历史记录应更新并显示新添加的事件。
我有以下AJAX调用,用于添加日志,并应刷新详细信息部分,在单击上面提到的“添加”按钮后触发:
$('#addLog').click(function () {
formData = {
logType: logType.value, // Parameter to add a new log
logComments: logComments.value, // Parameter to add a new log
agent: agent.value // Parameter to add a new log
}
$.ajax({
url: '@Url.Action("AddLog", "AgentUser")',
type: 'POST',
contentType: 'application/json',
dataType: 'json',
data: JSON.stringify(formData),
cache: false,
success: function (data) {
// Here I should refresh the the details section
// and clear the logType and logCommands inputs
}
});
});
在我的控制器中:
[HttpPost]
public ActionResult AddLog(string logType, string logComments, string agent, AgentUserValidatePhoneIndexViewModel vm)
{
DoDbStuff();
// Here I need to update the view model and view without having to
// refresh the page, so that it shows the recently added event.
return View(vm);
}
我的ViewModel:
public class AgentUserValidatePhoneIndexViewModel
{
public IEnumerable<AgentUserWithoutValidPhone> AgentUserWithoutValidPhoneList { get; set; }
}
我的模特:
public class AgentUserWithoutValidPhone
{
private string phone;
private DateTime creationDate;
public string Agent { get; set; }
public string Phone
{
get
{
return phone;
}
set
{
phone = PhoneNumberUtil.GetInstance().Parse("+" + value, String.Empty).NationalNumber.ToString();
}
}
public DateTime CreationDate
{
get
{
return creationDate;
}
set
{
creationDate = value;
TimeSpan timeSpan = (DateTime.Now) - creationDate;
TimeGoneBy = (timeSpan.Days != 0 ? timeSpan.Days + "d " : String.Empty) + timeSpan.Hours + "h";
}
}
public string TimeGoneBy { get; set; }
public DateTime LastLogEventDate { get; set; }
public LogEventTypePhone LastLogEvent { get; set; }
public IEnumerable<AgentUsersLog> EventList { get; set; }
}
我的观点:
@foreach (var agentUser in Model.AgentUserWithoutValidPhoneList)
{
<tr data-toggle="collapse" data-target="#details" class="accordion-toggle">
<td>
<button class="btn btn-default btn-sm"><span class="glyphicon glyphicon-collapse-down"></span></button>
</td>
<td>
@agentUser.Agent
</td>
<td>
@agentUser.Phone
</td>
<td>
@agentUser.CreationDate
</td>
<td>
@agentUser.TimeGoneBy
</td>
<td>
@agentUser.LastLogEventDate
</td>
<td>
@agentUser.LastLogEvent.GetDescription()
</td>
</tr>
<tr>
<td colspan="12" class="hiddenRow" id="">
<div class="accordian-body collapse" id="details">
<table class="table table-striped">
<thead>
<tr>
<input type="hidden" id="agent" value='@agentUser.Agent'>
<td>
@Html.DropDownList("LogEventTypePhone", EnumHelper.GetSelectList(typeof(Enums.LogEventTypePhone)), "Select log event",
new
{
id = "logType",
@class = "form-control"
})
</td>
<td colspan="2">
<input type="text" class="form-control" placeholder="Comments" id="logComments">
</td>
<td>
<a href="#" class="btn btn-default btn-sm" id="addLog">
<i class="glyphicon glyphicon-plus"></i>
</a>
</td>
</tr>
<tr>
<th>Event date</th>
<th>Event type</th>
<th>Comments</th>
<th>User</th>
</tr>
</thead>
<tbody>
@foreach (var e in agentUser.EventList)
{
<tr>
<td>@e.Date</td>
<td>@(((Enums.LogEventTypePhone)e.Subtype).GetDescription())</td>
<td>@e.Comments</td>
<td>@e.AspNetUsers.UserName</td>
</tr>
}
</tbody>
</table>
</div>
</td>
</tr>
}
如何将ViewModel与参数一起传递给我的控制器操作?现在,当我采取行动时,它是空的。我需要将其传递给操作,与DB交互,更新ViewModel,返回View并使用当前ViewModel更新它。
我从来没有做过我在这里想做的事情,我对此感到困惑。不确定它是否可能,或者我应该使用多个ViewModel。
答案 0 :(得分:1)
无需将视图模型传递给控制器并再次返回(这会不必要地降低性能)。如果您只想根据发布到控制器方法的值添加新行,则创建一个包含要在新行中显示的值的匿名对象(或AgentUsersLog
的新实例),将其返回作为json并通过添加新的<tr>
元素来更新DOM。
您的代码还存在一些其他问题,包括您在id
循环中创建无效html(重复foreach
属性)的事实。删除id
属性并使用类名与相对选择器一起使用(您显示的代码只会处理.click()
的第一个链接的id="addLog"
事件。您应该查看代码
@foreach (var agentUser in Model.AgentUserWithoutValidPhoneList)
{
<tr data-toggle="collapse" data-target=".details" class="accordion-toggle">
....
</tr>
<tr>
<td colspan="12" class="hiddenRow">
<div class="accordian-body collapse details"> // use class name
<table class="table table-striped">
<thead>
<tr>
<td>
<input type="hidden" class="agent" value='@agentUser.Agent'> // must be inside a td element
@Html.DropDownList("LogEventTypePhone", EnumHelper.GetSelectList(typeof(Enums.LogEventTypePhone)), "Select log event", new
{
id = "", // remove id
@class = "form-control logType" // add class name
})
</td>
<td colspan="2">
<input type="text" class="form-control logComments" placeholder="Comments"> // use class name
</td>
<td>
<a href="#" class="btn btn-default btn-sm addLog"> // use class name
<i class="glyphicon glyphicon-plus"></i>
</a>
</td>
</tr>
<tr>
....
</tr>
</thead>
<tbody>
@foreach (var e in agentUser.EventList)
{
....
}
</tbody>
</table>
</div>
</td>
</tr>
}
脚本变为
var url = '@Url.Action("AddLog", "AgentUser")';
$('.addLog').click(function () {
var table = $(this).closest('table');
var logType = table.find('.logType').val();
var logComments = table.find('.logComments').val();
var agent = table.find('.agent').val();
$.post(url, { logType: logType, logComments: logComments, agent: agent }, function(data) {
var row = $('<tr></tr>');
row.append($('<td></td>').text(data.Date));
.... // add other cells for data.Subtype, data.Comments and data.UserName
table.children('tbody').append(row);
});
});
然后在控制器中
[HttpPost]
public JsonResult AddLog(string logType, string logComments, string agent)
{
DoDbStuff();
// Build the data to return
var data = new
{
Date = .... ,
Subtype = .... ,
Comments = ..... ,
UserName = ....
};
return Json(data);
}
答案 1 :(得分:0)
您可以通过创建子对象来实现此目的。让我们假设模型“AgentUserValidatePhoneIndexViewModel”具有以下属性
然后生成formData,如下所示
formData = {
logType: logType.value, // Parameter to add a new log
logComments: logComments.value, // Parameter to add a new log
agent: agent.value // Parameter to add a new log
vm : { // Parameter to add values to view model
phone : answer.value,
agentDetail : agentDetail.value
}
}
查看此帖子以了解如何渲染部分视图
这篇文章解释了https://www.simple-talk.com/dotnet/asp.net/revisiting-partial-view-rendering-in-asp.net-mvc/