Adding class to error-span using unobtrusive validation - asp.net-mvc

I'm trying to get the example shown here to work within my project.
My code currently looks like:
<!-- jQuery.validate -->
#Scripts.Render("~/Bundles/jQueryVal")
<script type="text/javascript">
TypeScript.Framework.Helper.GlobalHelper.initClientValidation();
</script>
#Scripts.Render("~/Bundles/jQueryValUnobtrusive")
The two bundles are for jquery.validation.js and jquery.validation.unobtrusive.js as I've already know, that I have to include validation, make my changes, and then include unobtrusive.
Here the TypeScript:
const defaultOptions = {
errorClass: "help-block",
highlight(element) {
const idAttr = `#${$(element).attr("id")}Feedback`;
$(element).closest(".form-group").removeClass("has-success").addClass("has-error");
$(idAttr).removeClass("glyphicon-ok").addClass("glyphicon-remove");
},
unhighlight(element, errorClass, validClass) {
const idAttr = `#${$(element).attr("id")}Feedback`;
$(element).closest(".form-group").removeClass("has-error").addClass("has-success");
$(idAttr).removeClass("glyphicon-remove").addClass("glyphicon-ok");
},
errorElement: "span",
errorPlacement(error, element) {
if (element.length) {
error.insertAfter(element);
} else {
error.insertAfter(element);
}
}
};
$.validator.setDefaults(defaultOptions);
My login-view has two simple inputs for username and password:
#Html.LabelFor(m => m.Request.Username, new {#class = "sr-only"})
#Html.TextBoxFor(m => m.Request.Username, new {#class = "form-control"})
#Html.ValidationMessageFor(m => m.Request.Username)
However, the help-block class never gets assigned to the span.
On error it renders to:
<span class="field-validation-error" data-valmsg-for="Request.Username" data-valmsg-replace="true">
<span id="Request_Username-error" class="">The Username field is required.</span>
</span>
Any ideas?

Related

Submitting Form once but automatically being doubled / twice on POST method? ASP.NET MVC

I am currently working on a project in asp.net(v4.6) mvc(v5), it was working properly on first deployment on the remote server, after the first test trial its giving errors on forms when i submit on POST method.
It is automatically posting the form twice which is not required.
Places i checked for errors:
source code (also DEBUG)
searched and tried Logs
used tools to check why and from where this issue is occurring (no results)
I fix i found was the browser issue, when i changed from chrome to edge there was no errors... But there is still no notes on what the error is and how it is being generated.
Here is the View.cshtml
#using (Html.BeginForm("Create", "AdmissionCell", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<div class="col-md-12">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#*Input Fields Here*#
<div class="form-group">
<div class="col-md-offset-4 col-md-6">
<input type="submit" value="Save Student Record" class="btn btn-primary btn-lg" />
</div>
</div>
</div>
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
<script>
$(document).ready(function () {
$("#CNIC").change(function () {
$.get("/AdmissionCell/CheckCNIC",
{ cnic: $("#CNIC").val() },
function (data) {
if (data === 1) {
//alert("Sorry, CNIC already exists, Please enter unique CNIC. or ");
//location.reload();
var cnicStu = $("#CNIC").val();
if (window.confirm('Sorry, CNIC already exists, Please enter unique CNIC or Press "Ok" to goto student details.')) {
window.location.href = "/AdmissionCell/Details?cnic=" + cnicStu;
};
}
});
});
});
</script>
<script>
$(function () {
$('.cnic').on('keyup', function () {
var input = $('.cnic').val();
if (input.length == 5 || input.length == 13) {
$('.cnic').val(input + '-');
}
});
$('.gcnic').on('keyup', function () {
var input = $('.gcnic').val();
if (input.length == 5 || input.length == 13) {
$('.gcnic').val(input + '-');
}
});
});
</script>
}
I suspect your jqueryval bundle is included twice.
Once in the view (as shown) and also in your _layout file, so the events are bound twice

How to apply bootstrap v4 form input validation classes with the ASP.NET Razor syntax?

The following code:
View:(is-valid)
<div class="form-group">
#Html.LabelFor(m => m.Telefone, new { #class = "font-weight-bold" })
#Html.TextBoxFor(m => m.Telefone, new { #class = "form-control is-valid", #placeholder = "Digite seu telefone" })
#Html.ValidationMessageFor(m => m.Telefone, "", new { #class = "text-danger" })
</div>
View:(is-invalid)
<div class="form-group">
#Html.LabelFor(m => m.Telefone, new { #class = "font-weight-bold" })
#Html.TextBoxFor(m => m.Telefone, new { #class = "form-control is-invalid", #placeholder = "Digite seu telefone" })
#Html.ValidationMessageFor(m => m.Telefone, "", new { #class = "text-danger" })
</div>
Example: https://getbootstrap.com/docs/4.3/components/forms/#server-side
Any solution ?
Simple solution by using Tag Helpers:
<div class="form-group">
<input asp-for="Email" class="form-control">
<div class="invalid-feedback" style="display:block;">
<span asp-validation-for="Email"></span>
</div>
</div>
The class name is hardcoded: https://github.com/dotnet/aspnetcore/blob/v3.1.6/src/Mvc/Mvc.ViewFeatures/src/HtmlHelper.cs#L25
The only option is to alter CSS.
When you build Bootstrap from sources you can just add the next code into your SCSS file:
.input-validation-error {
#extend .is-invalid;
}
This will create an alias for existing .is-invalid.
Razor uses jQuery validation. You only need to hock jq-valid with Bootstrap:
$('form').validate().settings.errorClass += ' is-invalid';
$('form').validate().settings.validClass += ' is-valid';
//CONFIGURACAO BOOTSTRAP 4 PARA JQUERY VALIDATION PLUGIN
jQuery.validator.setDefaults({
onfocusout: function (e) {
this.element(e);
},
//onkeyup: false,
highlight: function (element) {
jQuery(element).closest('.form-control').addClass('is-invalid');
},
unhighlight: function (element) {
jQuery(element).closest('.form-control').removeClass('is-invalid');
jQuery(element).closest('.form-control').addClass('is-valid');
},
errorElement: 'div',
errorClass: 'invalid-feedback',
errorPlacement: function (error, element) {
if (element.parent('.input-group-prepend').length) {
$(element).siblings(".invalid-feedback").append(error);
//error.insertAfter(element.parent());
} else {
error.insertAfter(element);
}
},
});
Building off Seagull's answer for .Net 5 and Bootstrap 5 (I can't comment on his answer).
I was able to follow this guide, https://www.dotnetcatch.com/2019/05/16/adding-bootstrap-sass-to-asp-net-core/, to build a custom Bootstrap CSS that includes the ASP.NET validation class name so that you get the look of the Bootstrap validation controls.
#import "../lib/bootstrap/scss/bootstrap";
.input-validation-error {
#extend .is-invalid;
}
be sure to include :
"jquery .js
jquery.validate .js
jquery.validate.unobtrusive .js"

getting null value in textboxfor tool for date in mvc

I am adding bootstrap date in textboxfor tool and its showing also.
But, the problem is that I am getting null value in controller.
Here is my code
View
#using (Html.BeginForm("Create", "StaffRegistration", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
#Html.TextBoxFor(model => model.JoinDate, new { #class = "form-control", placeholder = "DD/MM/YYYY", Name = "date" })
}
Script File
$(document).ready(function () {
var date_input = $('input[name="date"]'); //our date input has the name "date"
var container = $('.bootstrap-iso form').length > 0 ? $('.bootstrap-iso form').parent() : "body";
date_input.datepicker({
format: 'dd/mm/yyyy',
container: container,
todayHighlight: true,
autoclose: true,
})
})
Controller
public ActionResult Create(StaffRegistrationViewModel staffRegistrationViewModel)
{
//here is my code
}
Now, when I click the button at that time at controller side null value is coming.[I saw by doing in debug mode]
In staffRegistrationViewModel, JoinDate field showing null value.
Thank You.
Generally Bootstrap DateTime Picker will Implement like this...
and in this way even you will get the value of selected datetime in post action method(in controller)...
// View Code
<div id="datefrom" class="input-group date">
#Html.TextBoxFor(model => model.FromDate, new { #class = "form-control", #readonly = "readonly", style = "position: static;" })
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
// Jquery Code
$('#datefrom').datetimepicker({
format: 'DD/MM/YYYY HH:mm:ss',
ignoreReadonly: true,
useCurrent: false});

Html.ValidationMessageFor() not rendering <span> element

I've been using Html.ValidationMessageFor for quite a long time in MVC 3. All of a sudden this extension is no longer working for me, but only in a particular view. The extension is used in a <form> tag and the page has the jquery.validate.min.js and jquery.validate.unobtrusive.min.js attached (among others). I've checked other pages of the site, and those views use the same call and the <span> element is generated.
Here is the markup I'm using:
<form id="assistanceRequestDiv" class="form-group js-more-assistance js-hidden">
<p>#Translation.TextByDomain("Assistance", "need-further-assistance-contact-customer-support")</p>
<div class="content-block left-text-children">
<div class="content-block__quarter-column">
#Html.LabelFor(x => x.AssistanceRequestFirstName)
#Html.ValidationMessageFor(x => x.AssistanceRequestFirstName)
#Html.TextBoxFor(x => x.AssistanceRequestFirstName, new {#class = "form-control", required = "required"})
</div>
<div class="content-block__quarter-column">
#Html.LabelFor(x => x.AssistanceRequestLastName)
#Html.ValidationMessageFor(x => x.AssistanceRequestLastName)
#Html.TextBoxFor(x => x.AssistanceRequestLastName, new {#class = "form-control", required = "required"})
</div>
<div class="content-block__quarter-column">
#Html.LabelFor(x => x.AssistanceRequestPhoneNumber)
#Html.ValidationMessageFor(x => x.AssistanceRequestPhoneNumber)
#Html.TextBoxFor(x => x.AssistanceRequestPhoneNumber, new {#class = "form-control"})
</div>
<div class="content-block__quarter-column set-vertical-align-bottom">
<button id="btnSubmitAssistanceRequest" class="btn btn--primary">#Translation.Text("submit")</button>
</div>
</div>
</form>
Data Annotations
[RequiredLocalized, DisplayNameLocalized("first-name")]
public string AssistanceRequestFirstName { get; set; }
[RequiredLocalized, DisplayNameLocalized("last-name")]
public string AssistanceRequestLastName { get; set; }
[RequiredLocalized, DisplayNameLocalized("phone-required")]
[RegularExpressionLocalized(#"(?:(?:\+?1\s*(?:[.-]\s*)?)?(?:(\s*([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9]‌​)\s*)|([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9]))\s*(?:[.-]\s*)?)([2-9]1[02-9]‌​|[2-9][02-9]1|[2-9][02-9]{2})\s*(?:[.-]\s*)?([0-9]{4})", "please-enter-a-valid-10-digit-phone-number", "Assistance")]
public string AssistanceRequestPhoneNumber { get; set; }
RequiredLocalized - Required attribute that returns a custom message. Works in other places of the site.
DisplayNameLocalized - DisplayName attribute with custom message. Works in other places.
Etc
This form is hidden by default and shown when the user clicks a certain button. Here are the scripts that are attached to the page:
<script src="/Scripts/jquery-1.8.3.min.js"></script>
<script src="/Scripts/jquery-ui-1.10.4.custom.min.js"></script>
<script src="/Scripts/jquery.unobtrusive-ajax.min.js"></script>
<script src="/Scripts/jquery.validate.min.js"></script>
<script src="/Scripts/jquery.validate.unobtrusive.min.js"></script>
<script src="/Scripts/jquery.validate.extensions.js"></script>
<script src="/Scripts/Shared/jQueryGlobalSettings.js"></script>
Using Javascript to return false if there are errors on the page in this format:
$('#btnSubmitAssistanceRequest').click(function (e) {
var $answer = $('.js-title');
var $reqFirstName = $('#AssistanceRequestFirstName');
var $reqLastName = $('#AssistanceRequestLastName');
var $reqPhoneNumber = $('#AssistanceRequestPhoneNumber');
// Check for empty fields
if ($reqFirstName.val().trim() == "") {
showErrorMessage($reqFirstName, 'First Name is required.');
} else {
clearErrorMessage($reqFirstName);
}
if ($reqLastName.val().trim() == "") {
showErrorMessage($reqLastName, 'Last Name is required.');
} else {
clearErrorMessage($reqLastName);
}
if ($reqPhoneNumber.val().trim() == "") {
showErrorMessage($reqPhoneNumber, 'Phone Number is required.');
} else {
clearErrorMessage($reqPhoneNumber);
}
// check if validation errors were thrown
if ($(".field-validation-error").length) return false;
$.post('/api/[obfuscated]/[obfuscated]', { answer: $answer.text(), firstName: $reqFirstName.val(), lastName: $reqLastName.val(), phoneNumber: $reqPhoneNumber.val() }, function (data) {
if (data.success) {
$('.request-assistance-success').css('display', 'inline');
$(".feedback-container").slideUp(400);
} else {
$('.request-assistance-failure').css('display', 'inline');
$(".feedback-container").slideUp(400);
}
});
e.preventDefault();
return true;
});
Replace
<button id="btnSubmitAssistanceRequest" class="btn btn--primary">#Translation.Text("submit")</button>
with
<input type="submit" id="btnSubmitAssistanceRequest" class="btn btn--primary" Text="#Translation.Text("submit")"/>
Submit form invokes the unobtrusive validations.

pass model from view to controller with html.actionlink

I am trying to get the model data from a strongly typed view to a controller.
Using the submit button is ok, I can get the data. Now I want to achieve the same with html.actionlink.
This is what I have:
View:
#model WordAutomation.Models.Document
#{
ViewBag.Title = "Document";
}
<script type="text/javascript">
$(function () {
$("#dialog").dialog();
});
</script>
<h2>Document</h2>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Document</legend>
<div class="editor-label">
#Html.LabelFor(model => model.ClientTitle)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ClientTitle)
#Html.ValidationMessageFor(model => model.ClientTitle)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ClientFullName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ClientFullName)
#Html.ValidationMessageFor(model => model.ClientFullName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ClientCustomSSN)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ClientCustomSSN)
#Html.ValidationMessageFor(model => model.ClientCustomSSN)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Preview", "PreviewWordDocument", "Home", null, new { id = "previewLink" })
</div>
<div id="dialogcontainer">
<div id="dialogcontent"><input type="submit" value="Create" /> </div>
</div>
#section Scripts {
<script type="text/javascript">
$(document).ready(function() {
$("#dialogcontainer").dialog({
width: 400,
autoOpen:false,
resizable: false,
title: 'Test dialog',
open: function (event, ui) {
$("#dialogcontent").load("#Url.Action("PreviewWordDocument", "Home")");
},
buttons: {
"Close": function () {
$(this).dialog("close");
}
}
});
$("#previewLink").click(function(e) {
e.preventDefault();
$("#dialogcontainer").dialog('open');
});
});
</script>
}
Controller:
public ActionResult Document()
{
return View();
}
[HttpPost]
public ActionResult Document(WordAutomation.Models.Document model)
{
Models.Utility.EditWord word = new Models.Utility.EditWord();
word.EditWordDoc(model);
return View("Display", model);
}
public ActionResult PreviewWordDocument()
{
var image = Url.Content("~/Content/preview.jpeg");
return PartialView((object)image);
}
The document actionresult can get the model, but I want to know how can I get the values from the actionlink which will trigger the PreviewWordDocument action.
Thanks in advance, Laziale
The form can only be posted using the submit button to the URL given by its action attribute.
You can however send the form data to a different URL using the jQuery post method, manually validating the form before it is sent.
That way you can send the form data to the PreviewWordDocument controller method and handle the response in order to show the preview in the desired div.
(It will be helpful if you give an id to the form, so you can easily find it using jQuery)
So your click event handler for the preview link will look like this:
$("#previewLink").click(function(e) {
e.preventDefault();
if($("#YourFormId").valid()){
$("#dialogcontainer").dialog('open');
}
});
In the open function of the dialog you will post the form (which was already validated) to the preview controller method, using the jQuery ajax function. The response will be loaded into the dialogContent div:
$.ajax({
type: "POST",
url: $("#previewLink").attr("href"), //the preview controller method
data: $("#YourFormId").serialize(),
success: function (data) {
//load ajax response into the dialogContent div
$("#dialogcontent").html(data);
},
error: function(xhr, error) {
$("#YourFormId").prepend('<div id="ajaxErrors"></div>')
.html(xhr.responseText);
}
});
Now you will now be able to receive the whole document in the PreviewWordDocument action:
public ActionResult PreviewWordDocument(WordAutomation.Models.Document model)
{
var image = Url.Content("~/Content/preview.jpeg");
return PartialView((object)image);
}
in a HTML page when you click on a submit button all the input elements inside the form which the submit button resides in will posted to server, but when you click on a anchor (<a> tag ). you only send a request with a Get method and without posting any value.but if you want to send particular value to the server with this approach you can do it by query string.you have used following to make a request :
#Html.ActionLink("Preview", "PreviewWordDocument", "Home", null,
new { id = "previewLink" })
this will produce :
<a id="previewLink" href="/Home/PreviewWordDocument"> Preview </a>
which is incorrect.to pass any value to the server with ActionLink use 4th parameter like this :
#Html.ActionLink("Preview", "PreviewWordDocument", "Home",
new { id = "previewLink" }, null)
the result from this code would be :
Preview
cheers!

Resources