[英]Modal form validation in asp.net core 2.1 and Razor pages
我有一个Details.cshtml页面,其中显示客户的详细信息以及customer.sites的链接列表。 在页面上,我创建了一个用于添加新站点的按钮,该按钮将打开一个包含用于输入新站点的表单的引导程序模式。
我遇到的问题是验证。 如果表单无效,则页面将重新加载,但模式会再次隐藏,这意味着除非用户再次单击添加站点按钮,否则将看不到asp-validation-for文本。 有什么方法可以使当ModelState.IsValid无效时,模式自动保持打开状态吗?
details.cshtml页面
@page "{id:int?}"
@model ServiceManager.Pages.Customers.DetailsModel
@{
ViewData["Title"] = "Details";
}
<h2>@Html.DisplayFor(model => model.Customer.Name)</h2>
<hr />
<!-- Modal -->
<div class="modal fade" tabindex="-1" role="dialog" aria-hidden="true" id="createSiteModal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Add New Customer Site</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Site.Description" class="control-label"></label>
<input asp-for="Site.Description" class="form-control" />
<span asp-validation-for="Site.Description" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Site.AddressLine" class="control-label"></label>
<textarea asp-for="Site.AddressLine" class="form-control"></textarea>
<span asp-validation-for="Site.AddressLine" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Site.City" class="control-label"></label>
<input asp-for="Site.City" class="form-control" />
<span asp-validation-for="Site.City" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Site.County" class="control-label"></label>
<input asp-for="Site.County" class="form-control" />
<span asp-validation-for="Site.County" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Site.Postcode" class="control-label"></label>
<input asp-for="Site.Postcode" class="form-control" />
<span asp-validation-for="Site.Postcode" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Site.Country" class="control-label"></label>
<input asp-for="Site.Country" class="form-control" />
<span asp-validation-for="Site.Country" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Site.Telephone" class="control-label"></label>
<input asp-for="Site.Telephone" class="form-control" />
<span asp-validation-for="Site.Telephone" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Site.Fax" class="control-label"></label>
<input asp-for="Site.Fax" class="form-control" />
<span asp-validation-for="Site.Fax" class="text-danger"></span>
</div>
<div class="form-group">
<input asp-for="Site.CommercialID" class="form-control" value="3" />
</div>
<div class="form-group">
<input type="button" value="Cancel" class="btn btn-danger" data-dismiss="modal" />
<input type="submit" value="Create" class="btn btn-success" />
</div>
</form>
</div>
</div>
</div>
</div>
<div class="btn-group" role="group">
<a class="btn btn-light" data-toggle="tooltip" data-placement="top" data-delay="200" title="Back to Customer List" asp-page="./Index">
<span class="fas fa-arrow-left fa-1x" style="color:#007bff"></span>
</a>
@if (Model.Customer.CustomerType == "Domestic")
{
<a class="btn btn-light" asp-page="./EditDom" asp-route-id="@Model.Customer.ID" data-toggle="tooltip" data-placement="top" data-delay="200" title="Edit Customer">
<span class="fas fa-user-edit fa-1x" style="color:#0c0cbe"></span>
</a>
}
else
{
<a class="btn btn-light" asp-page="./Edit" asp-route-id="@Model.Customer.ID" data-toggle="tooltip" data-placement="top" data-delay="200" title="Edit Customer">
<span class="fas fa-user-edit fa-1x" style="color:#0c0cbe"></span>
</a>
}
<a class="btn btn-light" asp-page="./Delete" asp-route-id="@Model.Customer.ID" data-toggle="tooltip" data-placement="top" data-delay="200" title="Delete Customer">
<span class="fas fa-user-times fa-1x" style="color:#b01111"></span>
</a>
</div>
<div class="row">
<div class="col-lg-4">
<div class="card border-info mb-3">
<h5 class="card-header bg-info text-white">Customer Details</h5>
<div class="card-body">
<dl class="row">
<dt class="col-5">
@Html.DisplayNameFor(model => model.Customer.AccountRef)
</dt>
<dd class="col-7">
@Html.DisplayFor(model => model.Customer.AccountRef)
</dd>
<dt class="col-5">
@Html.DisplayNameFor(model => model.Customer.ContactDate)
</dt>
<dd class="col-7">
@Html.DisplayFor(model => model.Customer.ContactDate)
</dd>
<dt class="col-5">
@Html.DisplayNameFor(model => model.Customer.Active)
</dt>
<dd class="col-7">
@Html.DisplayFor(model => model.Customer.Active)
</dd>
</dl>
</div>
</div>
</div>
<div class="col-lg-4">
<div class="card border-info mb-3">
<h5 class="card-header bg-info text-white">Customer Sites</h5>
<table class="table table-hover fixed-table">
<tr>
<th>Description</th>
<th>Location</th>
<th>Telephone</th>
</tr>
@foreach (var item in Model.Customer.Sites)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Description)
</td>
<td>
@Html.DisplayFor(modelItem => item.City)
</td>
<td>
@Html.DisplayFor(modelItem => item.Telephone)
</td>
<td>
<a class="rowlink" asp-page="/Sites/Details" asp-route-id="@item.ID"><i class="fa fa-chevron-right"></i></a>
</td>
</tr>
}
</table>
<div class="card-footer">
<!-- Button trigger modal -->
<button class="btn btn-link float-right" data-toggle="modal" data-target="#createSiteModal">
<span class="fa-stack fa-lg">
<i class="fas fa-circle fa-stack-2x" style="color:tomato"></i>
<i class="fas fa-stack-1x fa-inverse">+</i>
</span>
</button>
<div class="clearfix"></div>
</div>
</div>
</div>
</div>
Details.cshtml.cs页面
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using ServiceManager.Models;
namespace ServiceManager.Pages.Customers
{
public class DetailsModel : PageModel
{
private readonly CompanyContext _context;
public DetailsModel(CompanyContext context)
{
_context = context;
}
public Commercial Customer { get; set; }
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
Customer = await _context.Commercial
.Include(c => c.Sites)
.Include(c => c.Contacts)
.FirstOrDefaultAsync(m => m.ID == id);
if (Customer == null)
{
return NotFound();
}
return Page();
}
[BindProperty]
public Address Site { get; set; }
public async Task<IActionResult> OnPostAsync(int? id)
{
if (!ModelState.IsValid)
{
Customer = await _context.Commercial
.Include(c => c.Sites)
.Include(c => c.Contacts)
.FirstOrDefaultAsync(m => m.ID == id);
return Page();
}
_context.Address.Add(Site);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}
解决此问题的一种方法是在提交表单之前使用jQuery
执行客户端验证。 这样,模态保持打开状态,用户可以立即获得有关错误原因的反馈。
在这种情况下,另一种替代方法(可能是侵入性较小的方法)是将标志从服务器传递回客户端,并带有模型验证的状态,然后根据此类标志的值打开模态,例如
控制器 :
public async Task<IActionResult> OnPostAsync(int? id)
{
if (!ModelState.IsValid)
{
Customer = await _context.Commercial
.Include(c => c.Sites)
.Include(c => c.Contacts)
.FirstOrDefaultAsync(m => m.ID == id);
ViewData["ModelIsValid"] = false;
return Page();
}
ViewData["ModelIsValid"] = true;
_context.Address.Add(Site);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
查看 :
<script>
$(document).ready(function () {
@if(!(bool)ViewData["ModelIsValid"])
{
$("#createSiteModal").modal('show');
}
});
</script>
第二种方法的主要缺点是,模态将在页面呈现后弹出而不是保持打开状态。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.