将@Html.EditorFor“日期”值传回控制器,操作值并传回视图以填充下拉列表
Posted
技术标签:
【中文标题】将@Html.EditorFor“日期”值传回控制器,操作值并传回视图以填充下拉列表【英文标题】:pass @Html.EditorFor "Date" value back to Controller, manipulate value and pass back to view to populate Dropdown list 【发布时间】:2015-01-15 13:02:03 【问题描述】:我有以下 MVC 应用程序,请参见下面的前端:
“Invoice Date Created”是一个html5兼容的datepicker,基于以下方法:
http://www.aubrett.com/InformationTechnology/WebDevelopment/MVC/DatePickerMVC5.aspx
我对屏幕加载的要求如下:
1) 在日期和文本框更新的日期选择器“onSelect”上,我需要传递此值,例如2014/11/19 并将其操作为 yyyymm 格式(例如 201411)。有一个问题。它需要能够为当前时期以及上一时期创造这样的价值。
因此,2014/11/19 应使用两个选项填充“发票编号期间”下拉列表:
201411(本期)201410(上期)
有没有办法让我通过这个日期 2014/11/19 例如回到我的控制器,在那里我可以进行操作并将 201411 和 201410 返回到我的下拉列表?还是我想错了?我已经阅读了大量的 javascript 文章,但没有一篇完全符合我的需要。如何以及最好的方法是什么?
我是一个 MVC 和 Javascript 新手,所以很难理解这个..
编辑 - 这是我的代码:
Finance.cshtml:
@model List<FinanceMVC.Models.FinanceViewModel>
@
ViewBag.Title = "Index";
@using (Html.BeginForm("Finance", "Finance", FormMethod.Post, new @class = "form-horizontal" ))
<div class="col-md-1 fade in" style="margin-left: 5%; width: 100%; font-size: 11px; height: auto;">
<div id="div_Finance_Container" style="width: 100%; height: 80%; overflow: auto; text-align: left;" runat="server" class="scroll-pane">
<div style="height: 500px; overflow: auto;">
<div><a href="#" id="addNew" class="add-another-cat smallest">Add New</a></div>
<table id="dataTable" border="0">
<tr>
<th>Invoice Type</th>
<th>Invoice Number</th>
<th>Invoice Number Period</th>
<th>Invoice Date Created</th>
<th></th>
</tr>
@if (Model != null && Model.Count > 0)
int j = 0;
foreach (var i in Model)
<tr>
<td>
<div class="col-md-1" style="width: 20%;">
<select name="ddlInvoiceType">
@foreach (var item in Model)
foreach(var bItem in item.InvoiceType)
<option value="@bItem.Description">@bItem.Description</option>
</select>
</div>
</td>
<td>@Html.TextBoxFor(a => a[j].InvoiceNumber)</td>
<td>@Html.TextBoxFor(a => a[j].InvoiceNumberPeriod)</td>
<td>@Html.EditorFor(a => a[j].InvoiceDateCreated)</td>
<td>
@if (j > 0)
<a href="#" class="remove">Remove</a>
</td>
</tr>
j++;
</table>
<input type="submit" value="Save Bulk Data" />
</div>
</div>
</div>
@section Scripts
@Scripts.Render("~/bundles/jqueryval")
<script language="javascript">
$(function ()
$(document).on('change', '#InvoiceDateCreated', function ()
alert($(this).val());
);
);
</script>
<script type="text/javascript">
$(document).ready(function ()
$('#[0].InvoiceDateCreated').change(function ()
$('#[0].InvoiceDateCreated').text('sam');
);
);
</script>
<script language="javascript">
$(document).ready(function ()
//1. Add new row
$("#addNew").click(function (e)
e.preventDefault();
var $tableBody = $("#dataTable");
var $trLast = $tableBody.find("tr:last");
var $trNew = $trLast.clone();
var suffix = $trNew.find(':input:first').attr('name').match(/\d+/);
$trNew.find("td:last").html('<a href="#" class="remove">Remove</a>');
$.each($trNew.find(':input'), function (i, val)
// Replaced Name
var oldN = $(this).attr('name');
var newN = oldN.replace('[' + suffix + ']', '[' + (parseInt(suffix) + 1) + ']');
$(this).attr('name', newN);
//Replaced value
var type = $(this).attr('type');
if (type.toLowerCase() == "text")
$(this).attr('value', '');
// If you have another Type then replace with default value
$(this).removeClass("input-validation-error");
);
$trLast.after($trNew);
// Re-assign Validation
var form = $("form")
.removeData("validator")
.removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse(form);
);
// 2. Remove
$('a.remove').live("click", function (e)
e.preventDefault();
$(this).parent().parent().remove();
);
);
</script>
Finance.cs(模型):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
namespace FinanceMVC.Models
//public class Finance
//
//
public partial class FinanceViewModel
/*ID*/
[Required]
[Display(Name = "ID")]
public int ID get; set;
/*BINL_BIND_ID*/
[Required]
[Display(Name = "Invoice Type")]
//public int InvoiceType get; set;
public List<C_InvoiceType> InvoiceType get; set;
/*BINL_Inv_Num_Pointer*/
[Required]
[Display(Name = "Invoice Number")]
public char InvoiceNumber get; set;
/*BINL_Inv_Num_Period*/
[Required]
[Display(Name = "Invoice Number Period")]
public int InvoiceNumberPeriod get; set;
/*BINL_Created*/
[Display(Name = "Invoice Created Date")]
[Required]
[DataType(DataType.DateTime)]
public DateTime InvoiceDateCreated get; set;
/*BINL_SystemInserted*/
[Required]
[Display(Name = "Invoice System Inserted")]
public bool InvoiceSystemInserted get; set;
public class C_InvoiceType
public int ID get; set;
public string Description get; set;
FinanceController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using FinanceMVC.Models;
using System.Threading.Tasks;
using System.Data;
using System.Data.SqlClient;
namespace FinanceMVC.Controllers
public class FinanceController : Controller
public ActionResult Finance()
FinanceViewModel FVM = new FinanceViewModel();
// This is only for show by default one row for insert data to the database
List<FinanceViewModel> FinanceViewList = new List<FinanceViewModel>
new FinanceViewModel
ID = 0 , InvoiceType = ReturnInvoiceType(), InvoiceNumber = '\0', InvoiceNumberPeriod = 0, InvoiceDateCreated = DateTime.Now, InvoiceSystemInserted = false
;
return View(FinanceViewList);
//
// GET: /Finance/
/*Matches file name of Finance.cshtml*/
[HttpPost]
public ActionResult Finance(List<FinanceViewModel> model)
if (ModelState.IsValid)
return View(model);
//
// GET: /Finance/Welcome/
public string Welcome()
return "This is the Welcome action method...";
public static List<C_InvoiceType> ReturnInvoiceType()
string sQ = ""
+ " Select ID, BIND_Description \n"
+ " From Biller_InvoiceNum_DefSet with(nolock) \n"
;
try
using (SqlConnection sCon = new SqlConnection(Application_Info.sMOB_Master_Conn()))
if (sCon.State != ConnectionState.Open)
sCon.Open();
using (SqlCommand sCmd = new SqlCommand(sQ, sCon))
using (SqlDataReader sRdr = sCmd.ExecuteReader())
List<C_InvoiceType> list_InvoiceType = new List<C_InvoiceType>();
while (sRdr.Read())
list_InvoiceType.Add(new C_InvoiceType
ID = (int)sRdr["ID"],
Description = (string)sRdr["BIND_Description"]
);
return list_InvoiceType;
catch
return ReturnInvoiceType();
【问题讨论】:
为什么不直接在客户端使用 javascript/jqeury。您可以轻松创建这 2 个选项并更新下拉列表,而无需调用服务器。 您已将InvoiceNumberPeriod
的控件呈现为文本框,但您的问题说它是一个下拉菜单。你要哪个?
@StephenMuecke,它仍然是一个文本框,将其更改为下拉列表。因此,必须填充下拉列表。
@StephenMuecke,将对此进行进一步调查。对不起,就像我说的,我是一个 Javascript 菜鸟,所以很快看到解决方案有点棘手。
所以本质上,每次选择日期时,您都希望呈现 2 个选项,一个用于当前月份,一个用于上个月,格式为“yyyyMM”?
【参考方案1】:
编辑:
对于使用 MVC 5 而不是 MVC 5.1 的任何人,请继续阅读并在下面找到解决方法。对于使用 MVC 5.1 的任何人,请参阅 @StephenMuecke 的回答,因为这适用于 5.1。
原帖:
感谢@StephenMuecke,我找到了一个解决方案,以防其他人遇到同样的问题
东西。下面是我的完整解释和代码。
一些帖子建议使用 TextBoxFor 代替,但这会破坏 默认 html5 日期选择器。
基本上,我们的应用程序是一个空白的 MVC 5 应用程序(Visual Studio 2012 with Web Installer),
提出EditorFor控件不接受html属性作为参数的问题。请
请参阅下面的链接:
MVC5 and Bootstrap3: Html.EditorFor wrong class? How to change?
Asp.net MVC5 with Bootstrap EditorFor size
Is there a solution for using ASP.NET MVC 5 Html.EditorFor() and Bootstrap 3.0?
综上所述,MVC 5.1 具有此功能。任何使用 MVC 5 的人都不能像下面这样添加@class 属性:
@Html.EditorFor(a => a[j].InvoiceDateCreated, new htmlAttributes = new @class = "InvoiceDateCreated" )
相反,我使用了下面提到的以下解决方法:
Change id attribute of an html.editorfor helper in MVC4 with Razor
结果如下:
@Html.EditorFor(a => a[j].InvoiceDateCreated, null, "ID")
如果我们在 Chrome 中查看(再次感谢 Stephen),代码如下:
<input class="form-control datecontrol" data-val="true" data-val-date="The field Invoice Created Date must be a date." data-val-required="The Invoice Created Date field is required." id="myID" name="myID" type="date" value="2014/11/19" />
正如我们所看到的,现在我们可以在 jQuery 中使用它来呈现带有 id 属性的控件,如下所示:
<script>
function padLeft(nr, n, str)
return Array(n - String(nr).length + 1).join(str || '0') + nr;
$('#myID').change(function ()
var row = $(this).closest('tr');
var date = new Date($(this).val());
var currentMonth = date.getFullYear().toString() + padLeft(date.getMonth() + 1, 2);
date.setMonth(date.getMonth() - 1);
var previousMonth = date.getFullYear().toString() + padLeft(date.getMonth() + 1, 2);
var select = row.find('#InvoiceNumberPeriod').empty();
select.append($('<option></option>').val(currentMonth).text(currentMonth));
select.append($('<option></option>').val(previousMonth).text(previousMonth));
);
</script>
它现在完美运行。不确定它是否是最优雅的解决方案,或者它对“最佳实践”列表的评价有多高,但它确实有效。
【讨论】:
或者你可以使用@Html.TextBoxFor(a => a[j].InvoiceDateCreated, new @class = "InvoiceDateCreated", @type = "date" )
来呈现浏览器的数据选择器。而且由于您的问题在循环中呈现了此问题,因此您会生成重复的 id(无效的 html)和名称属性(因此它不会回发),因此它绝对是 not best practice :- )
谢谢,做了这个改变。真的很有帮助,@StephenMuecke,非常感谢。【参考方案2】:
您可以使用 jquery 完成此客户端,而无需调用服务器。由于您有多行,因此您需要为控件指定一个类名,以便可以选择它们,例如
@Html.EditorFor(a => a[j].InvoiceDateCreated, new htmlAttributes = new @class = "InvoiceDateCreated" )
并添加以下脚本
function padLeft(nr, n, str)
return Array(n - String(nr).length + 1).join(str || '0') + nr;
$('.InvoiceDateCreated').change(function ()
var row = $(this).closest('tr');
var date = new Date($(this).val());
var currentMonth = date.getFullYear().toString() + padLeft(date.getMonth() + 1, 2);
date.setMonth(date.getMonth() - 1);
var previousMonth = date.getFullYear().toString() + padLeft(date.getMonth() + 1, 2);
var select = row.find('.InvoiceNumberPeriod').empty();
select.append($('<option></option>').val(currentMonth).text(currentMonth));
select.append($('<option></option>').val(previousMonth).text(previousMonth));
);
【讨论】:
快来试一试。 请注意,您在呈现集合的方式方面存在许多问题。例如,您有一个删除函数来删除一行,但如果您删除了 5 行中的第 3 行,则只有前 2 行会回发(您没有Index
属性,因此如果名称索引器绑定失败不从零开始并且是连续的)。还有其他问题。
是的,我也意识到在非 html5 浏览器中“adEventListener”不再受支持,对吧?仍然会克服这些问题。不幸的是,认为 Javascript 方面存在问题。尝试实现更改和功能,但遇到了一些问题。会不断更新。感谢您迄今为止的所有反馈。
注意我在脚本的最后两行做了一些更正(忘记了一些引号)
谢谢,我只是在让它工作时遇到了一些麻烦。它永远不会触发我放置在 "$('.InvoiceDateCreated').change(function () " 部分中的警报。【参考方案3】:
如果你想从javascript调用控制器,你可以使用ajax post函数。
$.ajax(
type: "POST",
url: "Finance/Finance",
dataType: "json",
data:
// pass in some data
,
success: function (results)
// do something (or nothing) with the returned data
,
error: function (e)
alert(e.status + " - " + e.statusText);
);
【讨论】:
谢谢,我也会尽快尝试一下@Grentley。 我已经尝试过这种方法,但我恐怕无法实现?我已经到了这一点,在页面加载时它会返回到 url。但是,我需要在选定日期执行此操作的东西。我意识到这是我对 Javascript/ajax 等方面的知识缺乏。但我似乎无法做到这一点..以上是关于将@Html.EditorFor“日期”值传回控制器,操作值并传回视图以填充下拉列表的主要内容,如果未能解决你的问题,请参考以下文章