ASP.NET MVC 5 #Html.EditorFor and javascript datepicker - javascript

I'm using this MVC 5 code:
<div class="form-group">
#Html.LabelFor(model => model.Expiry_date, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Expiry_date, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Expiry_date, "", new { #class = "text-danger" })
</div>
</div>
And I would like to replace it with a datepicker like this one and still using the #Html.EditorFor() statement:
<div class="form-group">
#Html.LabelFor(model => model.Expiry_date, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<a href="javascript:;"
id="vacation"
data-type="date"
data-viewformat="yyyy-mm-dd"
data-pk="1"
data-placement="right"
data-original-title="Expiry date">
2016-03-28
</a>
</div>
</div>

I would like to propose an alternate suggestion to creating an EditorTemplate: Create an extension method instead. This will allow you to provide some overrides as well where needed. I just pasted your example in there with a couple of placeholders (could would need to be tweaked and tested).
public static MvcHtmlString DatePickerFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, DateTime>> expression, string controlId, string title)
{
// you could get additional model info from the metadata object
// var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
Func<TModel, DateTime> method = expression.Compile();
var date = method(htmlHelper.ViewData.Model);
var str = $"<div class=\"col-md-10\">{date.ToString("yyyy-MM-dd")}</div>";
return new MvcHtmlString(str);
}
You can then call this from your view:
<div class="form-group">
#Html.LabelFor(model => model.Expiry_date, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DatePickerFor(model => model.Expiry_date, "someId", "some title")
#Html.ValidationMessageFor(model => model.Expiry_date, "", new { #class = "text-danger" })
</div>
</div>

You can take the code for the desired datepicker that you have above and add it to the MVC Shared > EditorTemplates folder. You can add it as a new editor or overwrite an existing DateTime editor if you have one.
The editor templates in that folder are the ones used by MVC when you call #Html.EditorFor(...), and you can pass in an optional string to the call to force MVC to use a specific template.
See this MSDN article for more info.
https://msdn.microsoft.com/en-us/library/ee292027(v=vs.118).aspx

If you have the datepicker .js file downloaded.. all you have to do is render it in your _Layout View <script src="~/FolderName//*js file*/".. then in your HTML:
<div class="form-group">
#Html.LabelFor(model => model.Expiry_date, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Expiry_date, new { htmlAttributes = new { #class = "form-control datepicker" } })
#Html.ValidationMessageFor(model => model.Expiry_date, "", new { #class = "text-danger" })
</div>
</div>

Related

Binding jquery post data to c# type [duplicate]

I cannot figure out why my view only passes back a NULL for a model to my controller.
This is for an Edit Post method. I checked other controllers with Edit Post methods that are structured the same way as this one and they work fine. It seems to be just this view and controller.
Here is my view:
#model Non_P21_Quote_System_v1._0.Models.gl_code
#{
ViewBag.Title = "Edit";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Edit</h2>
#if (TempData["Message"] != null)
{
<div style="color:green">
#TempData["Message"]
</div><br />
}
#if (ViewBag.error != null)
{
<div style="color:red">
<h3>#ViewBag.error</h3>
</div><br />
}
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>gl_code</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.ID)
<div class="form-group">
#Html.LabelFor(model => model.GL_code, "GL Code", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.GL_code, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.GL_code, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.GL_description, "Gl Description", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.GL_description, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.GL_description, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.expense_type_ID, "Expense", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("expense_type_ID", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.expense_type_ID, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.eag, "Employee Account Group", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("eag", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.eag, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "gl_Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Here is my controller method:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit([Bind(Include = "ID,GL_code,GL_description,expense_type_ID,eag")] gl_code gl_code)
{
if (ModelState.IsValid)
{
db.Entry(gl_code).State = EntityState.Modified;
await db.SaveChangesAsync();
return RedirectToAction("gl_Index");
}
ViewBag.eag = new SelectList(db.employee_account_group, "ID", "eag_name");
ViewBag.expense_type_ID = new SelectList(db.expense_type, "ID", "type", gl_code.expense_type_ID);
return View(gl_code);
}
When I debug it, I see the model being passed in is of value NULL. I am seeing this on the controller side at the the parameters part of the Edit method.
Its null because your model contains a property named gl_code and you have also named the parameter for your model gl_code in the POST method.
Change the name of one or the other and the model will bind correctly.
What is happening internally is that the form submits a name/value pair for each successful form control, in your case gl_code=someValue. The DefaultModelBinder first initializes a new instance of your model. It then reads the form values and finds a match for the property in your model and sets it to someValue. But it also finds a match in the method parameters and tries set the value of the parameter to someValue, which fails (because you cannot do gl_code gl_code = "someValue";) and the model becomes null.
It appears you have a property on your view model called gl_code. In your controller, you also refer to the view model as gl_code.
Try changing this.
public async Task<ActionResult> Edit(gl_code gl_code)
To
public async Task<ActionResult> Edit(gl_code model)

Remove validation on fields from another partial view

I have two partial views in my application. One contains a select list to decide between payments methods. If the user chooses Direct debit another partial opens with the relevant input fields and validation. If they choose Cheque this form is hidden. However the validation isn't removed
Direct Debit Partial View
<div class="form-horizontal">
<div class="form-group">
#Html.Label("Sort Code", new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(Model => Model.SortCode12, new { #class = "control-label col-md-1", #readonly = "readonly" })
<div class="col-md-1"> - </div>
#Html.TextBoxFor(Model => Model.SortCode34, new { #class = "control-label col-md-1", #readonly = "readonly" })
<div class="col-md-1"> - </div>
#Html.TextBoxFor(Model => Model.SortCode56, new { #class = "control-label col-md-1", #readonly = "readonly" })
</div>
<div class="col-md-10">
#Html.ValidationMessageFor(model => model.SortCode12, "", new { #class = "text-danger" })
#Html.ValidationMessageFor(model => model.SortCode34, "", new { #class = "text-danger" })
#Html.ValidationMessageFor(model => model.SortCode56, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.Label("Account Number", new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(Model => Model.BankAccountNumber, new { #class = "control-label col-md-2", #readonly = "readonly" })
</div>
<div class="col-md-10">
#Html.ValidationMessageFor(model => model.BankAccountNumber, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.Label("Account Name", new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(Model => Model.BankAccountName, new { #class = "control-label col-md-10", #readonly = "readonly" })
</div>
<div class="col-md-10">
#Html.ValidationMessageFor(model => model.BankAccountName, "", new { #class = "text-danger" })
</div>
</div>
Payment method partial view
<div id="CurrentPaymentMethod">
<div class="panel-group">
<div class="panel panel-default">
<div class="cl panel-heading">
<h4 class="panel-title">
Payment Method
</h4>
</div>
<div class="panel-body">
<div class="form-group">
#Html.Label("Payment Method", new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(Model => Model.PaymentMethodID,
new SelectList(Model.PaymentMethods, "Id", "Description"),
"Select Payment Method",
new { #class = "form-control", #required = "required", #onchange = "ChangePaymentMethod(this.value)" })
</div>
<div class="col-md-10">
#Html.ValidationMessageFor(model => model.PaymentMethodID, "", new { #class = "text-danger" })
</div>
</div>
</div>
</div>
</div>
</div>
<script>
function ChangePaymentMethod(paymentMethodID)
{
#* Show Direct Debit section if the DD payment option (ID=0) has been selected*#
if (paymentMethodID == 0) {
document.getElementById("CurrentDirectDebitDetails").style.display = "block";
}
else {
document.getElementById("CurrentDirectDebitDetails").style.display = "none";
document.getElementById("SortCode34").removeAttribute("data-val-required");
document.getElementById("SortCode12").removeAttribute("data-val-required");
document.getElementById("SortCode56").removeAttribute("data-val-required");
document.getElementById("BankAccountNumber").removeAttribute("data-val-required");
document.getElementById("BankAccountName").removeAttribute("data-val-required");
}
}
At the bottom I have created some javascript to show and hide the direct debt from depending on the drop down selection item. This works however the validation remains
Any help with this would be appreciated
You can give specific class Name for all validation messages, errorMessagesForm1 form2 etc ...
then using this class to select the messages and hide it or remove it or whatever you want to do with it.
something like this,
#Html.ValidationMessageFor(model => model.PaymentMethodID, "", new { #class = "text-danger ErrMsgsForm2" })
js
var ErrorMSGs= document.getElementsByClassName("ErrMsgsForm2");
// Array of all error messages, loop through it
for(var i = 0; i < ErrorMSGs.length; i++){
ErrorMSGs[i].style.visibility = "hidden"; // or any other method, maybe change innerHTML etc
}

EditorFor field clear button with javascript

having Html code :
<div class="form-group has-feedback">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control", #placeholder = "Name" } })
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
<span class="form-control-clear glyphicon glyphicon-remove form-control-feedback"></span>
</div>
</div>
trying to make clear button with javascript :
$(document).ready(function() {
$('.form-control-clear').on("click", function () {
$(this).val('')
});
});
but not working

how to add Razor element dynamically with new name and id?

I have following razor code. I need to add this dynamically on button click in client side.
<div class="form-group" id="transitem" name="transitem">
<div class="col-md-11" id="tritem" name="tritem">
#Html.LabelFor(model => model.transaction_item_id, "transaction_item_id", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-3">
<div id="trans_dd_1" name="trans_dd_1">#Html.DropDownList("transaction_item_id", null, htmlAttributes: new { #class = "form-control", #id = "trans_id_#", #Name = "trans_id_#" })</div>
#Html.ValidationMessageFor(model => model.transaction_item_id, "", new { #class = "text-danger" })
</div>
<div>
#Html.LabelFor(model => model.transaction_itmQty, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-3">
#Html.EditorFor(model => model.transaction_itmQty, new { htmlAttributes = new { #class = "form-control", #id = "trans_qty_#", #Name = "trans_qty_#" } })
#Html.ValidationMessageFor(model => model.transaction_itmQty, "", new { #class = "text-danger" })
</div>
</div>
<div class="col-md-2"><input type="button" class="btnPlus" value="+" /></div>
</div>
</div>
I have written following script, but it is not working as expected. I need to change the name and id of trans_id_# and trans_qty_#. They are being generated by html helper, html.editorfor. Below is my script, which can copy the new element, but i am not able to change the id or name.
<script type="text/javascript">
var itm_cnt = 1;
$(document).ready(function () {
$(document).on("click", ".btnPlus", function () {
var new_clone = $('#tritem').clone();
itm_cnt = itm_cnt + 1;
var new_name = "trans_id_" + itm_cnt.toString();
$(new_clone).attr("name", "new_name");
$('#transitem').append(new_clone);
window.alert(itm_cnt);
});
});

Creating div dynamically with htmlhelpers inside?

I have problem with my MVC app which is shown in the pictures.
So when i click on the one of the checkboxes, script will be set the visible of the div to visible. But this is not good idea because the second div have a empty space above.
Checkboxes with script insdie:
<label><input type="checkbox" onclick="biurowyScript();" id="biurowyCheck" /> Pracownik biurowy</label>
<label><input type="checkbox" onclick="przewodnikScript();" id="przewodnikCheck" style="margin-left: 30px" /> Przewodnik</label>
biurowy div
<div id="biurowy" style="visibility: hidden">
<div class="form-group">
#Html.LabelFor(model => model.Pracownik_biurowy.Nazwa_uzytkownika, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Pracownik_biurowy.Nazwa_uzytkownika, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Pracownik_biurowy, "", new { #class = "text-danger" })
</div>
</div>
</div>
przewodnik div:
<div id="przewodnik" style="visibility: hidden">
<div class="form-group">
#Html.LabelFor(model => model.Przewodnik.Uprawnienia, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Przewodnik.Uprawnienia, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Przewodnik.Uprawnienia, "", new { #class = "text-danger" })
</div>
</div>
</div>
In scripts i only set visible of the divs to visible. But like i said this is not the good idea for this app. So what i can use to fix this ?
Use display="none" instead of visibility="hidden"
<div id="biurowy" style="display: none">
<div class="form-group">
#Html.LabelFor(model => model.Pracownik_biurowy.Nazwa_uzytkownika, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Pracownik_biurowy.Nazwa_uzytkownika, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Pracownik_biurowy, "", new { #class = "text-danger" })
</div>
</div>
</div>
EDIT:
When you use visibilt=hidden it keeps the space, while using display=none you it does not keep the space. You can show it with jquery the same way, i mean $(item).show()

Categories