Display validation message - c#

I am struggling with displaying validation messages on my webpage.
I have a javascript function which does client side validation and highlights the fields with invalid values. Besides highlighting the fields, I want to display a message on my webpage which I dont know how to do.
Here is my javascript function:
$(function () {
$("#Save").click(Validate);
});
function Validate() {
var invalidValues = [];
var validValues = [];
var Code = $("#Code").val();
var Description = $("#Description").val();
var Status = $("#Status ").val();
var requiredFields = { '#Code' : Code,
'#Description' : Description,
'#Status ' : Status };
$.each(requiredFields, function (key, value) {
if (value.length == 0) {
invalidValues.push(key);
}
else { validValues.push(key); }
});
var invalidFields = invalidValues.toString();
var validFields = validValues.toString();
if (invalidValues.length > 0){
$(invalidFields).addClass("highlighted");
$(validFields).removeClass("highlighted");
return false;
}
$(validFields).removeClass("highlighted");
}
Here is my webpage:
<div>
<table>
<tr>
<th>
Code
</th>
<td>
<input maxlength="4" id="Code" type="text"/>
</td>
</tr>
<tr>
<th>
Description
</th>
<td>
<input id="Description" type="text"/>
</td>
</tr>
<tr>
<th>
Status
</th>
<td>
<input id="Status" type="text"/>
</td>
</tr>
<tr>
<th>
</th>
<td>
<button id="Save" type="button">Save</button>
</td>
</tr>
</table>
</div>
I want to display a message at the bottom of my webpage saying "Please enter valid values for: Code". I store invalid values in a variable "invalidValues "in my js function "Validate" How can I access those values in my webpage?
I also have a few questions about what is the best way of doing validations? Client side vs server side? also, is it better to display a pop-up validation message or a highlighted message embedded on webpage?

I'm not familiar enough with MVC to answer about how to use built-in validation (like plain-old ASP.Net has), assuming that MVC has it to begin with.
That little disclaimer out of the way, the code below should validate your form for required fields and throw a message on the page for your users:
$(function () {
var Validate = function Validate(e) {
var allFieldsValid = false, // boolean flag to cache result
invalidFields = [], // array for selectors
validFields = [], // array for selectors
requiredFields = [ // array of selectors to validate against
"#Code",
"#Description",
"#Status"
],
message = $('<span />').addClass('validation-message').text('* This is a required field.');
$(requiredFields.join(', ')).each(function (i, elem) {
//requiredFields.join(', ') should return "#Code, #Description, #Status"
var field = $(elem)
value = field.val();
if (value.length === 0) {
invalidFields.push(field.selector);
} else {
validFields.push(field.selector);
}
});
allFieldsValid = invalidFields.length === 0; // if there are no invalid fields, all fields must be valid
$('span.validation-message').remove(); // remove any previous validation messages
$(validFields.join(', ')).removeClass("highlighted"); // remove class from all valid fields
// add class to all invalid fields and append message
$(invalidFields.join(', ')).addClass("highlighted").append(message.clone());
if (!allFieldsValid) {
e.preventDefault(); // invalid fields, prevent event from bubbling
}
return allFieldsValid; // return result
};
$("#Save").click(Validate);
});
As far as your other questions about validation:
What is the best way of doing validations? Client side vs server side?
also, is it better to display a pop-up validation message or a highlighted message embedded on webpage?
In order:
There is no versus. There is either server-side, or both client-side and server-side. This is because you cannot rely on your users to have JavaScript enabled and therefore you cannot rely on your client-side to run. Think of client-side like a pre-filter. The purpose of client-side is to do a "precheck" and prevent unwanted data from using up bandwidth (sending to server and the "bad data" response) and from using processing cycles on the server. Client-side will also be more responsive than server-side (because there's no request-response) but that's really only a perceived performance issue for high-latency connections. Server-side will always run and so validation should always start on the server.
This is matter of preference for your users. Personally, I wouldn't code a pop-up unless someone asked me very nicely to do so, mostly because it takes focus away from the form and requires extra work (usually one click) to dismiss. A highlighted message does not have to do either of these, and some validation routines are even nice enough to put focus on the first invalid field. If there's room on the page for it, a message next to each field is handy and can look very nice. If however, space on the page is at a premium, most validation routines will put an asterisk next to the field and have all of the individual validation messages in one spot on the page.

after your table you can keep a div without anything written in it. but with an id.
And after you validaten just access that div by document.get('div_id') and then assign value to it.
Using this you can even show validation with colors like red and others.
And showing like this is better than a popup because when a softaware comes number of cliks should be minimum.

Just add place holders for your error message in your HTML. For example:
<td>
<input id="Description" type="text"/><span id="descriptionErrorPlaceholder" />
</td>
Then in your javascript, use jQuery or regular javascript to add your warning message.
$("#descriptionErrorPlaceholder").text("Warning message");

If you're already using jQuery, you may be able to get approval to user the jQuery Validation plug-in, since it comes standard with Microsoft MVC applications now whenever you start a new project. That being said, I do recognize how hard it can be to get plug-ins approved, since I'm supporting different government clients. It looks like you could add a tag with each input element, and then modify the class for that span to show and hide it, similar to what you already do when highlighting the input box.
I can't test this on my work machine, but I would think it's something like:
$(function () {
$("#Save").click(Validate);
});
function Validate() {
var invalidValues = [];
var validValues = [];
var Code = $("#Code").val();
var Description = $("#Description").val();
var Status = $("#Status ").val();
var requiredFields = { '#Code' : Code,
'#Description' : Description,
'#Status ' : Status };
$.each(requiredFields, function (key, value) {
if (value.length == 0) {
invalidValues.push(key);
}
else { validValues.push(key); }
});
var invalidFields = invalidValues.toString();
var validFields = validValues.toString();
if (invalidValues.length > 0){
$(invalidFields).addClass("highlighted");
$(validFields).removeClass("highlighted");
$(invalidFields + "Validator").addClass("showValidation");
$(invalidFields + "Validator").removeClass("hideValidation");
return false;
}
$(validFields).removeClass("highlighted");
$(validFields + "Validator").removeClass("showValidation");
$(invalidFields + "Validator").addClass("hideValidation");
}
With the HTML
<div>
<table>
<tr>
<th>
Code
</th>
<td>
<input maxlength="4" id="Code" type="text"/><span id="CodeValidator" class="hideValidation" />
</td>
</tr>
<tr>
<th>
Description
</th>
<td>
<input id="Description" type="text"/><span id="DescriptionValidator" class="hideValidation" />
</td>
</tr>
<tr>
<th>
Status
</th>
<td>
<input id="Status" type="text"/><span id="StatusValidator" class="hideValidation" />
</td>
</tr>
<tr>
<th>
</th>
<td>
<button id="Save" type="button">Save</button>
</td>
</tr>
</table>
</div>

Related

ASP.NET Core 5 MVC Render string from action in view

I try to display a string from Action in a View. This sounds like a very simple and easy task, but I don't get it how to do this.
My async Action returns Content Result:
public async Task<IActionResult> DisplayName(string key)
{
// Retrieves the requested culture
var rqf = Request.HttpContext.Features.Get<IRequestCultureFeature>();
// Culture contains the information of the requested culture
var culture = rqf.RequestCulture.Culture;
return Content(await Task.FromResult(_displayProvider.GetDisplayName(key, culture.Name)));
}
My View is very simple html:
#model List<MyModel>
<table class="table table-bordered table-striped datatable">
<thead class="table-head-dark">
<tr>
<th>
#Html.DisplayNameFor(model => model.First().Id)
</th>
<th>
Actions
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Id)
</td>
<td>
<partial name="_EditDetailButton" model="#item.Id" />
<partial name="_DeleteButton" model="#item" />
</td>
</tr>
}
</tbody>
</table>
Instead of #Html.DisplayNameFor(model => model.First().Id) I want to Display a user-defined value. The user-defined value is returned from the Action.
I tried #Url.Action("DisplayName", "DisplayName", new { key = "MyModel.Id" }) but this is rendering an Url.
I tried Html.RenderAction("DisplayName", "DisplayName", new { key = "LastName" }) but RenderAction does not exist in ASP.NET Core 5.
I could call a static Class e. g. DisplayNameProvider.GetDisplayName("MyModel.Id", ???) but i dont know how to get the choosen culture to pass it to the method.
How do I get this working? I am also not familiar with components in ASP.NET Core.
Or is there a completely different solution for displaying strings, which the user has defined and save to the database? The DisplayNameProvider is retrieving the strings from database and handles caching.
UPDATE:
The Goal is to store and change displaynames for properties in the database. The user can change the displaynames. In my example the user wants a different displayname for the column header. I cannot use resource files as these are static and cannot be changed during runtime.
This is my DisplayNameProvider.GetDisplayName Method:
public string GetDisplayName(string ressourceKey, string language)
{
var ressources = GetCached(language);
var item = ressources.FirstOrDefault(r => r.ResourceKey == ressourceKey);
return item.Text;
}
Thanks in advance
I ended up using a string localizer, which returns the desired value for my properties.
Now i can use displaynamefor and it shows the value of the language. E.g.:
#Html.DisplayNameFor(model => model.MyProperty)

Change TextBox Value and Update On Ajax Call

I am working on an ecommerce site where I am stuck on the cart management. Basically before login, products are kept in a session and I am trying to update the product quantity stored in the session using Ajax. I mean whenever I write in the 'Quantity To Change', the changed value should be reflected in the 'Quantity' column.
Note: I've shortened the post and figured out why it wasn't firing while debugging. Actually I was unable to get the id of the associated product. Now it passes the id. That's it. Now I've another issue - The TextBox are being created dynamically with a for loop. I used developer tools to figure out how the TextBoxes are generated dynamically and it is something like this:
For Product 1: cartDetails_0__Quantity
For Product 2: cartDetails_1__Quantity
I am wondering how to grab the quantity or values from the dynamically generated TextBoxes. If I put the generated id from HTML directly to Ajax, then it updates the quantity. Otherwise it doesn't. I've tried to use a loop in Ajax but I think, I am getting it wrong. Please see the View.
The view:
<table border="1" width="100%" cellpadding="4">
<thead>
<tr>
<th style="text-align:center;">Name</th>
<th style="text-align:center;">Price</th>
<th style="text-align:center;">Quantity</th>
<th style="text-align:center;">Quantity To Change</th>
</tr>
</thead>
<tbody>
#if (ViewBag.CartDetails != null)
{
for (int i = 0; i < cartDetails.Count(); i++)
{
<tr>
<td style="text-align: center; display:none;">#Html.DisplayFor(model => cartDetails[i].ProductId)</td>
<td id="ID" style="text-align: center;">#Html.DisplayFor(model => cartDetails[i].ProductName)</td>
<td style="text-align: center;">#Html.DisplayFor(model => cartDetails[i].Price)</td>
<td style="text-align: center;">#Html.DisplayFor(model => cartDetails[i].Quantity, new { #class = "quantityUpdate" })</td>
<td style="text-align: center;">#Html.TextBoxFor(model => cartDetails[i].Quantity, new { #class = "quantity", data_id = cartDetails[i].ProductId } )</td>
</tr>
}
}
</tbody>
</table>
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script type="text/javascript">
var url = '#Url.Action("UpdateCart")';
$(".quantityUpdate").change(function () {
var id = $(this).data('id');
var i = 0;
$('.quantityUpdate').each(function (i, item) {
$.post(url, { id: id, Quantity: $("#cartDetails_"+i+"__Quantity").val() }, function (response) {
if (response) {
$("#TotalPrice").load(window.location + " #TotalPrice");
}
});
})
alert(id);
alert($("#cartDetails_"+i+"__Quantity").val());
});
Here is an image sample that I am trying:
$('.quantity').change(function(){
$('.quantityUpdate').val($('.quantity').val());
// put code here
});
Instant Change
$('.quantity').keyup(function(){
$('.quantityUpdate').val($('.quantity').val());
// put code here
});
If the idea is to call ajax when you change the value in .quality textbox then this is how you should do:
$('.quantity').change(function(){
//your ajax call
});

MVC Dialog Save Refreshes Table Stops Working

I have been using the code from the article ASP.NET MVC: Ajax Dialog Form Using jQuery UI and it mostly works. I created a grid that lists records and each record has a link to bring up a dialog box to edit the record. After the record has been changed the save button is pressed and the grid is updated using ajax. This works great, but the problem comes after the first record save and the ajax refresh of the grid. If the link to edit the record is clicked again the dialog box doesn't come up, only the partial view is shown. I am guessing, but it appears the partial view that I am trying to bring up again doesn't recognize the parent container. Any ideas?
Display the partial view that contains the grid:
<div id="VehicleHold">
#Html.Partial("_VehicleHold")
</div>
The partial view that makes up the dialog:
#using VehicleWeb.MVCHelpers
#{
int agreementNumber = 0;
var countData = ViewBag.VehicleHoldViewModel as System.Collections.Generic.IEnumerable<VehicleWeb.Model.VehicleHoldViewModel>;
if (countData != null)
{
if (countData.Count() > 0)
{
agreementNumber = (int)countData.DefaultIfEmpty().First().AgreementNumber;
<table cellpadding="0" cellspacing="0" border="0" class="table table-striped table-bordered">
<thead>
<tr class="table-header">
<th>Edit</th>
<th>Delete</th>
<th>
Type
</th>
<th>
Year
</th>
<th>
Make/Model
</th>
<th>
Plate
</th>
<th>
VIN
</th>
<th>
Num Pass
</th>
</tr>
</thead>
<tbody>
#{
foreach (var item in (ViewBag.VehicleHoldViewModel as System.Collections.Generic.IEnumerable<VehicleWeb.Model.VehicleHoldViewModel>))
{
<tr>
<td>
#Html.ImageDialogLink("UpdateVehicleHold", "Exposure", new { id = item.RID }, "Edit Hold Vehicle", "VehicleHold", Url.Action("RefreshVehicleHold/" + agreementNumber), Html.ResolveUrl("~/pics/edit-button.png"), "Edit Hold Vehicle", "600", "800", new { style = "text-decoration:none;" }, new { style = "text-decoration:none; border-style: none;" })
</td>
<td>
<div title="Vehicle Year">#item.EditType.ToString()</div>
</td>
<td>
<div title="Vehicle Year">#item.AutoYear.ToString()</div>
</td>
<td>
<div title="Vehicle Make/Model">#item.MakeModel.ToString()</div>
</td>
<td>
<div title="Vehicle Plate Number">#item.DistVehNo.ToString()</div>
</td>
<td>
<div title="Vehicle VIN">#item.IDNumber.ToString()</div>
</td>
<td>
<div title="Number Of Passengers">#item.NumOfPassengers.ToString()</div>
</td>
</tr>
}
}
</tbody>
</table>
}
}
}
I am new at asking questions here, so just let me know if you need to see more code.
EDIT:
I don't know if it the position of the jQuery files matters for this. I have been messing around with the position today and haven't found success. I do have the jQuery file on the main form that it used to wire up the dialog box. After the AJAX refreshes the DIV, the edit link seems to loose all knowledge about the any of the parent code. My latest theory is it could be something to do with this code. Could it be because it is in a ready block?
$(document).ready(function () {
$.ajaxSetup({
cache: false
});
// Wire up the click event of any current or future dialog links
$('.dialogLink').on('click', function () {
var element = $(this);
// Retrieve values from the HTML5 data attributes of the link
var dialogTitle = element.attr('data-dialog-title');
var dialogWidth = element.attr('data-dialog-width');
var dialogHeight = element.attr('data-dialog-height');
var updateTargetId = '#' + element.attr('data-update-target-id');
var updateUrl = element.attr('data-update-url');
// Generate a unique id for the dialog div
var dialogId = 'uniqueName-' + Math.floor(Math.random() * 1000)
var dialogDiv = "<div id='" + dialogId + "'></div>";
// Load the form into the dialog div
$(dialogDiv).load(this.href, function () {
$(this).dialog({
modal: true,
resizable: false,
title: dialogTitle,
closeOnEscape: false,
width: dialogWidth,
height: dialogHeight,
buttons: [
{
text: "Save",
icons: { primary: "ui-icon-check" },
click: function () {
// Manually submit the form
var form = $('form', this);
if ($(form).valid()) {
$(form).submit();
$(this).dialog('close');
}
}},
{
text: "Cancel",
icons: { primary: "ui-icon-closethick" },
click: function () {
$(this).dialog('close');
$(this).empty();
}
}]
});
// Enable client side validation
$.validator.unobtrusive.parse(this);
// Setup the ajax submit logic
wireUpForm(this, updateTargetId, updateUrl);
});
return false;
});
});
function wireUpForm(dialog, updateTargetId, updateUrl) {
$('form', dialog).submit(function () {
// Do not submit if the form
// does not pass client side validation
if (!$(this).valid()) {
return false;
}
// Client side validation passed, submit the form
// using the jQuery.ajax form
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function (result) {
// Check whether the post was successful
if (result.success) {
// Close the dialog
$(dialog).dialog('close');
$(dialog).empty();
// Reload the updated data in the target div
$(updateTargetId).load(updateUrl);
} else {
alert('failure');
// Reload the dialog to show model errors
$(dialog).html(result);
// Enable client side validation
$.validator.unobtrusive.parse(dialog);
// Setup the ajax submit logic
wireUpForm(dialog, updateTargetId, updateUrl);
}
}
});
return false;
});
}
It some times happens when we keep the script in the main view it will bind the event for the first time but won't work after a postback, try moving the script in the partial view, if it doesn't work share some more code and will see what is wrong

Accessing text of all td text using jquery in an application

Hi I want to access text present in all section of my application. I cannot use id because in one application there are different tables with different id's. I want to access text name whenever I place mouse on that td cell irrespective of table so I can't use id. Please suggest me a way to do this using JQuery. The text which I want to access are from asp.net aspx page.
In jquery, you can apply a hover event to every td which fetches it's text. put the text in a variable, then pass it on to your .aspx handler with ajax. here is a simple example. its a good idea to put this script block in your ready function, or near the end of your document.
jQuery
$('td').hover(function () {
//mouse over
//get the data
var tdText = $(this).text();
console.log(tdText);
//do something with the data
var jqxhr = $.ajax("handler.aspx?text=" + tdText)
.done(function () {
console.log("success");
//do something
})
.fail(function () {
console.log("error");
//do something else
});
},
function () {
//mouse out
console.log("mouse-out");
}
);
I can only help you with determining if the mouse cursor is above any td element. You will need to modify the code to fit your needs to display something useful.
HTML:
<p id="message"> </p>
<table>
<tr>
<td>Data 1</td>
<td>Data 2</td>
<td>Data 3</td>
</tr>
<tr>
<td>Data A</td>
<td>Data B</td>
<td>Data C</td>
</tr>
</table>
JS:
addEventListener("mouseover", function(event) {
if (event.toElement.localName == 'td')
$('#message').html("You are in a table cell");
else
$('#message').html(" ");
}, false);
I also created a fiddle for you to test: http://jsfiddle.net/m3EmK/

Using jQuery to post back to Controller

In my web page, I have a series of tables that basically just contain rows of information. Each of these is given an id in a for loop and I'm trying to reference them from outside that. I added classes to both the table and a 'Save Changes' button.
Essentially, my goal is for the user to be able to drag and drop rows around, thereby changing the order. Then they can click the 'Save Changes' button and this will post back to the server with the relevant information.
I am having trouble matching up the button to the relevant table and thereby submitting the id's of each row back to the server in an array. I have written the code to be able to be able to get the ids from each of the tables and their current order, but I don't know how to assign this to an array from within the button click jQuery.
Here is the View:
#foreach (var collection in Model.Collections)
{
<h2>#collection.Season</h2>
#Html.ActionLink("Delete Collection", "DeleteCollection", new { controller = "Edit", brand = collection.Brand.Name, season = collection.Season })
#Html.ActionLink("Edit Collection", "EditCollection", new { controller = "Edit", brand = collection.Brand.Name, season = collection.Season })
#Html.ActionLink("Add Image", "CreateImages", new { controller = "Edit", season = collection.Season })
<p>
To change the ordering of images, drag and drop to your desired position and then click the Save Changes button on the appropriate collection.
</p>
<table class="table-collection" id="table-#collection.Id">
<tr class="nodrop nodrag">
<th>
Id
</th>
<th>
Description
</th>
<th>
Image
</th>
<th>
Options
</th>
</tr>
#foreach (var image in collection.Images)
{
<tr id="#collection.Id-#image.Id">
<td class="dragHandle showDragHandle">
#image.Id
</td>
<td>
#image.Description
</td>
<td>
<img src="#Url.Content("~/" + image.Location)" alt="#image.Description" />
</td>
<td>
<ul>
<li>
#Html.ActionLink("Edit", "EditImage", new { controller = "Edit", brand = image.Collection.Brand.Name,
season = image.Collection.Season, imageId = #image.Id } )
</li>
<li>
#Html.ActionLink("Delete", "DeleteImage", new
{
controller = "Edit",
brand = image.Collection.Brand.Name,
season = image.Collection.Season,
imageId = #image.Id
})
</li>
</ul>
</td>
</tr>
}
</table>
<p>
<input type="submit" value="Save Changes" class="save-order" id="saveTable-#collection.Id"/>
</p>
}
Here is the jQuery so far:
$(document).ready(function () {
$(".table-collection").tableDnD();
$(".save-order").click(function (e) {
e.preventDefault();
$.ajax({ url: window.location.href,
type: 'POST',
data: { ids: $("--ASSIGN ARRAY HERE--"
});
The jQuery to iterate through each row is essentially this:
function(table, row) {
var rows = table.tBodies[0].rows;
var debugStr = "Row dropped was "+row.id+". New order: ";
for (var i=0; i<rows.length; i++) {
debugStr += rows[i].id+" ";
}
I see you are using input type submit which is exclusively used to postback forms. What you need to do is wrap every table up in a form with something like this:
#using(Html.BeginForm("Action", "Controller", new{ collectionId = collection.Id }))
{
<input type="submit" value="Save Changes" class="save-order" />
}
Note that this will cause a 'post-back' of the form to Action, Controller. Specify the collection id inside the route values to identify the specific collection.
Do note, you need to add input type hidden with the id's value otherwise the ids' won't get serialised - all you have to specify is the name attribute
<td class="dragHandle showDragHandle">
<input type="hidden" name="ids" value="#(image.Id)" />
#image.Id
</td>
Then you can intercept the call then do it via ajax with:
$(".save-order").click(function(e) {
e.preventDefault();
var form = $(this).closest('form');
if(form.validate()) {
$.post(form.attr('action'), form.serialize(), function() {
alert('The new image order has been saved.');
});
}
return false;
});
The accepting controller action method will probably have this signature
public ActionResult Action(int collectionId, int[] ids)
{
//Do stuff here
return Request.IsAjaxRequest() ? null : View();
}
Now it should support graceful degradation if javascript is disabled (does a normal form submit, otherwise does it via ajax)
Hope this helps :)
You can grab all of the IDs with something like this:
var IDs = [];
$("#mydiv").find("span").each(function(){ IDs.push(this.id); });
In your scenerio, do something like this:
$(document).ready(function ()
{
$(".table-collection").tableDnD();
$(".save-order").click(function (e)
{
var IDs = [];
$("#yourtable").find("draggable-tr-class").each(function(){ IDs.push(this.id); });
e.preventDefault();
$.ajax(
{
url: window.location.href,
type: 'POST',
data: { ids: IDs }
);
}
})
i have been create demo in jsfiddle using json
http://jsfiddle.net/viyancs/4ffb3/11/
if you use like that demo in your server must be get parameter `JSONFile' after that parse this json for what do you want.actually the demo not same with your case but i think you can use this by your logic.

Categories