asp.net-mvc - 在 ASP.NET MVC 中使用一种形式创建模型的多个实例
问题描述
我正在构建一个表单,该表单创建一个具有不同模型列表作为属性的模型。这是模型:
public class JobViewModel
{
[Required]
public string JobName { get; set; }
[Required]
public string JobTotal { get; set; }
public bool Recurring { get; set; }
public List<ServiceViewModel> ExtraServices { get; set; }
}
这是 ServiceViewModel 类:
public class ServiceViewModel
{
public string ServiceName { get; set; }
public string ServiceTotal { get; set; }
}
任何单个 JobViewModel 都可以有 0-4 个与之关联的额外服务,因此在表单中,用户可以根据需要添加和删除额外的服务字段。这是创建 JobViewModel 的表单,以及一些允许用户添加和删除额外服务字段的 jQuery:(编辑:这是 _AddJobPartial 部分视图)
@{
//create unique id's so the ajax toggle and delete scripts only affect one widget.
var addJobWidgetId = "add-job-widget" + Model.JobId;
var addServiceWidgetId = "add-service-widget" + Model.JobId;
var addServiceButtonId = "add-service-button" + Model.JobId;
var widgetTitleId = "widget-title" + Model.JobId;
var deleteButtonId = "delete-button" + Model.JobId;
var widgetId = "widget-" + Model.JobId;
}
<div class="row" id="@widgetId">
<div class="border border-dark p-1 m-3">
<div id="job-header" class="d-flex justify-content-between">
<div>
<label class="widget-title-text" id="@widgetTitleId" for="job-name">Job:</label>
<input type="text" id="job-name" />
</div>
<div>
<button class="btn btn-danger btn-sm deleteButton" id="@deleteButtonId">X</button>
</div>
</div>
<div id="@addJobWidgetId" class="add-job-widget border border-dark">
<div class="form-group">
<label for="total-cost-input">Job Total</label>
<input type="text" id="total-cost-input" />
</div>
<div class="form-group">
<input type="checkbox" value="recurring" id="recurring_box" name="recurring_box"/>
<label for="recurring_box">Is this job recurring?</label>
</div>
<div class="p-1 extra-service-widget">
<button class="btn btn-info btn-sm" id="@addServiceButtonId">
Add extra service
</button>
<!--EXTRA SERVICE-->
<div id="@addServiceWidgetId">
</div>
<!---->
</div>
</div>
</div>
</div>
<script>
var servicesAdded = 0;
$("#" + "@addServiceButtonId").click(function (e) {
e.preventDefault();
servicesAdded++;
$.ajax({
type: "GET",
url: "/Daysheet/GetExtraServicePartial/" + servicesAdded.toString(),
headers: {
"RequestVerificationToken": requestVerificationToken
}
}).done(function (data, statusText, xhdr) {
console.log("Done");
$("#" + "@addServiceWidgetId").append(data);
}).fail(function (xhdr, statusText, errorText) {
console.log("Failed");
$("#" + "@addServiceWidgetId").text(JSON.stringify(xhdr));
});
});
</script>
这是单击上述表单上的“添加额外服务”按钮时创建的部分视图:
@{
var extraServiceListId = "extra-service-list" + Model.ServiceId;
var extraServiceWidgetId = "extra-service-widget" + Model.ServiceId;
var serviceTotalId = "service-total" + Model.ServiceId;
var deleteServiceId = "delete-service" + Model.ServiceId;
}
<div class="p-1 border border-dark" id="@extraServiceWidgetId">
<select id="@extraServiceListId">
<option>Extra services...</option>
<option value="purewater">Pure water</option>
<option value="powerwashing">Power washing</option>
<option value="roofwashing">Roof washing</option>
<option value="awningclean">Awning clean</option>
</select>
<input type="text" id="@serviceTotalId" placeholder="Service total" />
<button class="btn btn-danger btn-sm deleteButton float-right" id="@deleteServiceId">X</button>
</div>
<script>
$(document).on('click', '#' + '@deleteServiceId', function (e) {
e.preventDefault();
const elementToRemove = document.getElementById("@extraServiceWidgetId");
jQuery(elementToRemove).slideToggle().fadeOut('slow', function () {
elementToRemove.remove();
});
});
</script>
我想知道如何在提交作业表单时为每个额外的服务小部件创建一个 ServiceViewModel,并将它们附加到 JobViewModel 上的 ExtraServices 属性中。
我在这里找到了一些非常接近我需要的东西,但我不确定这个解决方案如何处理添加然后删除字段的用户,这会导致索引错误。该链接提到他们的解决方案能够解决该问题,但我不明白发生了什么。
编辑:
这是带有表单元素的实际视图。此视图有一个按钮,用于添加我在上面发布的 _AddJobPartial 部分视图。
这是 GetCommission.cshtml,它由我在下面发布的控制器操作之一返回。
@{
ViewData["Title"] = "Get Commission";
Layout = "~/Views/Shared/_DaysheetSubLayout.cshtml";
}
@model GetCommissionsViewModel
<form method="post">
<div class="row">
<div class="col-md-5 offset-1">
<div id="jobs-div" class="flex-fill p-2">
</div>
</div>
<div class="col-md-3 offset-1 d-flex align-items-center justify-content-center submit-jobs-wrapper">
<input class="btn btn-outline-primary w-100 h-100 submit-jobs-button"
type="submit"
value="Submit" />
</div>
</div>
</form>
<input type="button" id="add-job-button" value="Add a Job" data-url="@Url.Action("GetAddJobsPartial", "Daysheet")" />
@section scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
<script type="text/javascript">let requestVerificationToken = $("input[name='__RequestVerificationToken']").val();
var numClicked = 0;
$("#add-job-button").click(function () {
console.log("Controller Button clicked");
console.log($("#add-job-button").data("url"));
numClicked++;
console.log(numClicked);
$.ajax({
type: "GET",
url: "/Daysheet/GetAddJobsPartial/" + numClicked.toString(),
headers: {
"RequestVerificationToken": requestVerificationToken
}
}).done(function (data, statusText, xhdr) {
console.log("Done");
$("#jobs-div").append(data);
}).fail(function (xhdr, statusText, errorText) {
console.log("Failed");
$("#jobs-div").text(JSON.stringify(xhdr));
});
});</script>
}
这是我的控制器类中的相关操作:
[HttpPost]
public IActionResult GetCommission(CrewDaysheetsListViewModel crewDaysheetsListViewModel)
{
var getCommissionsViewModel = new GetCommissionsViewModel { DaysheetIds = crewDaysheetsListViewModel.CommissionsViewDaysheetIds };
return View(getCommissionsViewModel);
}
public IActionResult GetAddJobsPartial(string Id)
{
var addJobPartialViewModel = new AddJobPartialViewModel { JobId = Id};
return PartialView("_AddJobsPartial", addJobPartialViewModel);
}
public IActionResult GetExtraServicePartial(string Id)
{
var extraServicePartialViewModel = new ExtraServicePartialViewModel { ServiceId = Id };
return PartialView("_ExtraServicePartialView", extraServicePartialViewModel);
}
我用于这些页面的视图模型非常简单:
public class GetCommissionsViewModel
{
public List<string> DaysheetIds { get; set; }
}
public class AddJobPartialViewModel
{
public string JobId { get; set; }
}
public class ExtraServicePartialViewModel
{
public string ServiceId { get; set; }
}
我将 JobId 和 serviceId(可能可以将它们组合成一个 ViewModel)与局部视图一起使用,为它们的元素提供唯一的 id,因此删除按钮会删除正确的局部视图等。这个数字会在每次按下按钮时迭代_AddJobPartial 和 _ExtraServicePartial 的底部。
解决方案
推荐阅读
- pine-script - 为整个回测周期制定多时间框架安全功能
- flutter - Flutter:持久的底部导航栏在页面之间导航时重建所有页面
- postgresql - JSONB 忽略 Jackson 序列化包含
- spring-boot - HttpMessageNotReadableException 的模棱两可的 @ExceptionHandler 方法
- javascript - 通过javascript中的两个属性计算JSON
- google-apps-script - 简化 Google Apps 表中的 .setFormula 代码
- node.js - 无法在 WebStorm 中调试 Node.js Express 应用程序
- serverless - Serverless Deploy 仅在第一次工作,然后发生可恢复的错误 (ETIMEDOUT)
- c# - 如何为此处的 api c# 生成 Oauth1.0 的签名
- macos - MacOS 上的 GridDB 自动生成警告