如何在使用Ajax.Begin表单时更新多个div以及如何在模式弹出窗口

时间:2017-01-24 05:31:16

标签: asp.net-mvc

您好我正在尝试使用Bootstrap模式在asp .net mvc中创建一个页面(CRUD操作)。我研究了一些文章,发现部分观点最适合这种方法。我已经完成了大部分功能,但遇到了一些问题。请检查并指导。

这是我的主要索引视图。这是将在其他页面中使用的局部视图。此视图显示插入到数据库中的数据,并具有为添加和编辑操作呈现部分视图的Div:

<div class="grading" id="tblUserEducation">
    <div class="persn-detl sp-0">
        <p>
            <h3>Education</h3>
            <a href="javascript:void()" data-toggle="modal" data-target="#userEducationModal">Add Education</a>
        </p>
        @foreach (var item in Model.userEducationVm)
        {

            <div class="col-xs-12">

                <h5>@Html.DisplayFor(modelItem => item.School) </h5>
                <div>@Html.DisplayFor(modelItem => item.Degree), @Html.DisplayFor(modelItem => item.Fieldofstudy), @Html.DisplayFor(modelItem => item.Grade)</div>
                @if (item.Activities != null)
                {
                    <p>
                        Activities: @Html.DisplayFor(modelItem => item.Activities)
                    </p>
                }
                <p>From Year: @Html.DisplayFor(modelItem => item.FromYear) To Year @Html.DisplayFor(modelItem => item.ToYear)</p>
                @if (item.Description != null)
                {
                    <p>
                        Description:<br />
                        @Html.DisplayFor(modelItem => item.Description)
                    </p>
                }
                <div class="add-editing">
                    <ul>
                        <li><a href="javascript:void()" onclick="editUserEducation(@item.Id)"><i class="fa fa-pencil-square-o" aria-hidden="true"></i></a></li>
                    </ul>
                </div>
            </div>
        }
    </div>

</div>




<!-- Modal -->
<div class="modal fade" id="userEducationModal" role="dialog" data-backdrop="static" data-keyboard="false">
    <div class="modal-dialog">

        <!-- Modal content-->
        <div class="modal-content">
            <div class="modal-header">
                <button id="btnCloseEducationModal" type="button" class="close" data-dismiss="modal">&times;</button>
                <h4 class="modal-title">Education</h4>
            </div>
            <div class="modal-body" id="divUserEducation" style="height:500px;overflow-x:auto !important;">
                @{Html.RenderAction("Create", "UserEducation"); }
            </div>
            <div class="modal-footer">&nbsp;</div>
        </div>

    </div>
</div>

我的创建局部视图(删除了一些HTML):

@using (Ajax.BeginForm("Create", "UserEducation", new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "divUserEducation" }))
{
    @Html.AntiForgeryToken()

    <div>
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            <label for="School" class="form-control-label">School:</label>

            @Html.EditorFor(model => model.School, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.School, "", new { @class = "text-danger" })
        </div>

        <div class="form-group">
            <label for="Degree" class="form-control-label">Degree:</label>

            @Html.EditorFor(model => model.Degree, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.Degree, "", new { @class = "text-danger" })
        </div>



    </div>
    <div>
        <input type="submit" value="Save" class="btn btn-success" />
    </div>
}

这是我的索引和创建控制器:

public ActionResult Index()
{
    var model = new UserEducationViewModel
    {
        userEducationVm = userEducationService.getUserEducationAllRecords(),
        YearsInDropDown = clsCommonMethods.getYearsForDropDown()
    };
    return PartialView("_UserEducationIndex", model);
}

[HttpPost]
public ActionResult Create(UserEducationViewModel vObj)
{
    try
    {
        if (ModelState.IsValid)
        {
            UserEducation obj = new UserEducation();
            obj.School = vObj.School;
            obj.Degree = vObj.Degree;
            obj.Fieldofstudy = vObj.Fieldofstudy;
            obj.Grade = vObj.Grade;
            obj.Activities = vObj.Activities;
            obj.FromYear = vObj.FromYear;
            obj.ToYear = vObj.ToYear;
            obj.Description = vObj.Description;
            obj.Description = vObj.Description;
            userEducationService.insertUserEducation(obj);
            return RedirectToAction("Index");
        }
        else
        {
            vObj.YearsInDropDown = clsCommonMethods.getYearsForDropDown();
            return PartialView("~/Areas/MemberArea/Views/UserEducation/_UserEducationCreate.cshtml", vObj);
        }
    }
    catch
    { return RedirectToAction("Index"); }
}

以下是我面临的一些问题:

  1. 我创建了自定义验证,只适用于服务器端。因此,当Model.State无效时,我想显示带有服务器错误的create popup。为此,我将UpdateTargetId属性设置为“divUserEducation”(部分创建视图呈现的位置)。这显示错误消息,但是当没有错误消息并且数据被提交给服务器时,它会在弹出窗口中显示索引视图。
  2. 我想在数据成功保存时更新索引视图,并希望在出现任何验证错误时显示包含错误消息的创建表单。

    如果我将UpdateTargetId更改为“tblUserEducation”,它会更新索引页面上的新条目,但是当出现验证错误时,它不会在弹出窗口中显示创建页面。

    这是我的ViewModel类:

      public class UserEducationViewModel : IValidatableObject
    {
        public int Id { get; set; }
        public string UserId { get; set; }
    
        [Required]
        public string School { get; set; }
    
        [Required]
        public string Degree { get; set; }
    
        [Required]
        [Display(Name = "Field of Study")]
        public string Fieldofstudy { get; set; }
    
        [Required]
        public string Grade { get; set; }
    
        public string Activities { get; set; }
    
        [Required]
        [Display(Name = "From Year")]
        public Nullable<int> FromYear { get; set; }
    
    
        [Required]
        [Display(Name = "To Year")]
        public Nullable<int> ToYear { get; set; }
    
    
        public string Description { get; set; }
    
        public virtual AspNetUser AspNetUser { get; set; }
    
        public List<UserEducation> userEducationVm { get; set; }
    
        public List<SelectListItem> YearsInDropDown { get; set; }
    
        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
        {
            if (ToYear < FromYear)
            {
                yield return new ValidationResult("To Year cannot be smaller than From year.", new[] { nameof(ToYear) });
            }
    
    
        }
    }
    

1 个答案:

答案 0 :(得分:0)

Ajax.BeginForm()替换为Html.BeginForm()并使用jquery ajax()方法提交表单,如果有错误,请让方法返回JsonResult个错误。然后,如果有错误,您可以使用错误更新DOM,或者如果成功,只需根据表单控件中已有的值为新元素添加html(该方法需要返回的唯一额外数据)是您创建的对象的新ID。

您的表单将

@using (Html.BeginForm("Create", "UserEducation"))
{
    .... // form controls etc as above
}

以及处理提交的脚本

var url = '@Url.Action("Create", "UserEducation")';
$('form').submit(function(e) {
    e.preventDefault(); // cancel the default submit
    if (!$(this).valid()) {
        return; // exit if there are client side errors
    }
    var formData = $(this).serialize();
    $.post(url, formData, function(response) {
        if (response.success) {
            var id = response.id;
            // Build html for new item based on the values in the form
            // See notes below
            $('#userEducationModal').hide(); // Close the modal form
        } else {
            $.each(response.errors, function(index, item) {
                // Find the corresponding element generated by ValidationMessageFor()
                var placeholder = $('span[data-valmsg-for="' + item.propertyName + '"]');
                var message = $('<span></span>').text(item.errorMessage);
                placeholder.addClass('field-validation-error').removeClass('field-validation-valid').append(message);
            }
        }
    });
});

你的控制器方法将是

[HttpPost]
public JsonResult Create(UserEducationViewModel vObj)
{
    if (!ModelState.IsValid)
    {
        var errors = ModelState.Keys.Where(k => ModelState[k].Errors.Count > 0).Select(k => new { propertyName = k, errorMessage = ModelState[k].Errors[0].ErrorMessage });
        return Json( new { success = false, errors = errors });
    }
    try
    {
        // Map the view model to the data model, save and return the new ID
        return Json( new { success = true, id = obj.Id })
    }
    catch
    {
        // Not sure what you want to do here, but returning a friendly error message seems appropriate
    }
}

要添加html,最简单的方法是在隐藏的div元素中添加“模板”,例如

<div id="template" style="display:none">
    <!-- Repeat the same html that is in your foreach loop without the object values, but add class names so elements can be easily selected -->
    <div class="col-xs-12">
        <h5 class="school"></h5>
        <div class="degree"></div>
        ....
</div>

如果您为包含这些类名的对象创建自定义DisplayTemplate,那就更容易了,然后您可以用

替换foreach循环
@Html.DisplayFor(m => m.userEducationVm)

将为集合中的每个项生成正确的html,然后添加

<div id="template" style="display:none">@Html.DisplayFor(m => m.NewUser)</div>

其中,属性NewUser是视图模型中UserEducationViewModel的默认实例。然后添加新html的代码变为

var clone = $('#template').clone();
// update the values based on the form controls
clone.find('.school').text($('#School').val());
...
// Append it to the DOM
tblUserEducation.append(clone.html);