我正在尝试创建一个表,其中子行(每行总是一个子行)用作详细信息部分。在此详细信息部分中,用户将能够查看日志历史记录,并且还能够输入特定的日志。输入新日志并单击“添加”按钮后,日志历史记录应更新并显示新添加的事件。

我有以下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和参数一起传递到控制器动作中?现在,当我开始行动时,它是空的。我需要将其传递给操作,与数据库交互,更新ViewModel,返回到View并使用当前ViewModel更新它。

我从来没有做过我想在这里做的事情,对此我感到困惑。不知道这是否有可能,或者我应该使用几个ViewModel。

最佳答案

无需将视图模型传递给控制器​​,然后再传递回去(这只会不必要地降低性能)。如果您只是想根据发布到控制器方法的值添加新行,则创建一个包含要在新行中显示的值的匿名对象(或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);
}

10-05 20:29
查看更多