[英]pass @Html.EditorFor “Date” value back to Controller, manipulate value and pass back to view to populate Dropdown list
I have the following MVC application, see front-end below: 我有以下MVC应用程序,请参见下面的前端:
"Invoice Date Created" is a html5 compatable datepicker based on the following method: “发票日期已创建”是基于html5的兼容日期选择器,其基于以下方法:
http://www.aubrett.com/InformationTechnology/WebDevelopment/MVC/DatePickerMVC5.aspx http://www.aubrett.com/InformationTechnology/WebDevelopment/MVC/DatePickerMVC5.aspx
My requirement on screen load is the following: 我对屏幕加载的要求如下:
1) On datepicker "onSelect" of date and textbox updates, I need to pass this value eg 2014/11/19 and manipulate it to be in the format of yyyymm (eg 201411). 1)在日期选择器“ onSelect”的日期和文本框更新上,我需要传递此值(例如2014/11/19)并将其操纵为yyyymm格式(例如201411)。 There's a catch. 有一个陷阱。 It needs to be able create such a value for the current period, as well as the previous period. 它需要能够为当前期间以及上一个期间创建这样的值。
So, 2014/11/19 should populate "Invoice Number Period" Dropdown list with two options namely: 因此,2014/11/19应该在“发票编号期间”下拉列表中填充两个选项,即:
201411 (for current period) 201411 (当前期间)
201410 (for previous period) 201410 (上期)
Is there a way I can pass this date 2014/11/19 eg back to my controller where I can do the manipulation and return 201411 and 201410 back to my dropdown list? 有什么方法可以将日期2014/11/19传递回我的控制器,在那里我可以进行操作并将201411和201410返回到我的下拉列表? Or am I thinking about this the wrong way? 还是我在想这是错误的方式? I have read plenty of Javascript articles but none do exactly what I need to do. 我已经阅读了很多Javascript文章,但没有一篇完全符合我的需要。 How and what is the best way to go about this? 最好的方式和方法是什么?
I am an MVC and Javascript newby, so struggeling to get my head around this one.. 我是MVC和Javascript的新手,因此努力争取这一点。
Edit - Here is my code: 编辑-这是我的代码:
Finance.cshtml : 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 (Model): 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 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();
}
}
}
You can do this client side using jquery without the need to call the server. 您可以使用jquery进行此客户端操作,而无需调用服务器。 Since you have multiple rows, you will need to give your controls a class name so they can be selected, for example 由于您有多行,因此需要为控件提供一个类名,以便可以选择它们,例如
@Html.EditorFor(a => a[j].InvoiceDateCreated, new { htmlAttributes = new { @class = "InvoiceDateCreated" }})
and add the following scripts 并添加以下脚本
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));
});
If you want to call controller from javascript, you can use ajax post function. 如果要从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);
}
});
EDIT: 编辑:
For anyone using MVC 5 and not MVC 5.1, keep reading and find workaround below. 对于使用MVC 5而非MVC 5.1的任何人,请继续阅读并在下面找到解决方法。 For anyone using MVC 5.1, please see @StephenMuecke 's answer, as this works for 5.1. 对于使用MVC 5.1的任何人,请参见@StephenMuecke的答案,因为它适用于5.1。
Original Post: 原始帖子:
Credits to @StephenMuecke, I have found a solution in case someone else struggles with the same 归功于@StephenMuecke,我发现了一个解决方案,以防其他人为此感到困扰
thing. 事情。 Here is my complete explanation and code below. 这是我下面的完整解释和代码。
Some posts suggested using TextBoxFor instead, but this breaks the Default html5 datepicker . 有些帖子建议改用TextBoxFor ,但这会破坏Default html5 datepicker 。
Basically, our application is a blank MVC 5 application (Visual Studio 2012 with Web Installer) which 基本上,我们的应用程序是一个空白的MVC 5应用程序(带有Web Installer的Visual Studio 2012),
poses the problem that the EditorFor control does not accept htmlattributes as parameters. 带来了一个问题,即EditorFor控件不接受html属性作为参数。 Please 请
see link(s) below: 请参阅下面的链接:
MVC5 and Bootstrap3: Html.EditorFor wrong class? MVC5和Bootstrap3:Html.Editor对于错误的类? How to change? 如何改变?
Asp.net MVC5 with Bootstrap EditorFor size 带Bootstrap编辑器的Asp.net MVC5
Is there a solution for using ASP.NET MVC 5 Html.EditorFor() and Bootstrap 3.0? 是否有使用ASP.NET MVC 5 Html.EditorFor()和Bootstrap 3.0的解决方案?
From the above, MVC 5.1 has this functionality. 综上所述,MVC 5.1具有此功能。 Anyone using MVC 5 will not be able to add the @class attribute like below: 使用MVC 5的任何人将无法添加@class属性,如下所示:
@Html.EditorFor(a => a[j].InvoiceDateCreated, new { htmlAttributes = new { @class = "InvoiceDateCreated" }})
Instead I used the following workaround mentioned below: 相反,我使用了下面提到的以下解决方法:
Change id attribute of an html.editorfor helper in MVC4 with Razor 使用Razor在MVC4中更改html.editorfor帮助程序的id属性
and this is the result: 结果是:
@Html.EditorFor(a => a[j].InvoiceDateCreated, null, "ID")
If we look in Chrome (thanks again Stephen), this results in the code: 如果我们使用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" />
As we can see this renders the control with an id attribute now which we can use in our jQuery, see below: 如我们所见,这将呈现一个具有id属性的控件,该属性现在可以在jQuery中使用,请参见下文:
<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>
And it works perfectly now. 现在,它可以完美运行。 Not sure if its the most elegant solution or how far it rates up the "best practice" list, but it works. 不知道它是否是最优雅的解决方案,还是它在“最佳实践”列表中的排名有多高,但这是可行的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.