Adding a list of complex data models to form - javascript

I'm using Entity Framework 7 with ASP.NET MVC 5.
I have some forms that look like this. Clicking on one of the "new" buttons brings up a Bootstrap modal that looks like this. Submitting the modal form adds a new entity to the database before appending its name and primary key to the selectlist.
This works, but if the user changes their mind, the item(s) created via the modal (location in this case) stick around forever. So ideally none of the child items would be created until the main form is finished. While the example only has two simple fields, other data models have more than half a dozen, which may include complex fields of their own (but preventing that wouldn't be a horrible restriction).
So what's the best way to do this, nested divs serialized by JavaScript? Nested divs would also make it easy to allow reordering by the user, which is the end goal.
Does ASP.NET have a better way to handle this?

This feels hacky, but it works.
Using BeginCollectionItem, you can have the modal add hidden input elements to the DOM.
I wrote an action method that returns JSON with the modelstate (valid/invalid) and errors or partial HTML for invalid and valid submissions, respectively. Based on this, JavaScript either adds the errors to the summary or adds the requisite label and hidden inputs to the initial form.
Then have the main form's viewmodel contain an ICollection of your data model, called Contacts in below code, and ASP.NET handles the data binding with no troubles.
Example:
_CollectionItem.cshtml (partial HTML added to main form after valid submission)
#model Project.Models.ContactCreateViewModel
<li>
<div class="collection-item">
#using (Html.BeginCollectionItem("Contacts"))
{
<span class="item-name">#Model.LastName, #Model.FirstName</span> <span class="btn btn-danger delete-item">Delete</span>
#Html.HiddenFor(model => model.FirstName)
#Html.HiddenFor(model => model.LastName)
#Html.HiddenFor(model => model.PhoneNumber)
#Html.HiddenFor(model => model.PhoneExt)
#Html.HiddenFor(model => model.Email)
}
</div>
</li>
_CreateModal.cshtml (partial used for the body of the modal)
#model Project.Models.ContactCreateViewModel
<div class="modal-header">
<button type="button" class="close btn-modal-close" data-dismiss="modal"><i class="fas fa-times"></i></button>
<h4 class="modal-title">New Contact</h4>
</div>
<div class="modal-body">
#using (Html.BeginForm("CreateModal", "Contacts", FormMethod.Post, new { id = "new-contact-form" }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummaryPlaceholder()
#* First Name *#
<div class="form-group">
#Html.LabelFor(model => model.FirstName, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-8">
#Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.FirstName, "", new { #class = "text-danger" })
</div>
</div>
#* Last Name *#
<div class="form-group">
#Html.LabelFor(model => model.LastName, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-8">
#Html.EditorFor(model => model.LastName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.LastName, "", new { #class = "text-danger" })
</div>
</div>
#* Phone Number *#
<div class="form-group">
#Html.LabelFor(model => model.PhoneNumber, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-8">
#Html.EditorFor(model => model.PhoneNumber, new { htmlAttributes = new { #class = "form-control phone" } })
#Html.ValidationMessageFor(model => model.PhoneNumber, "", new { #class = "text-danger" })
</div>
</div>
#* Phone Ext *#
<div class="form-group">
#Html.LabelFor(model => model.PhoneExt, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-8">
#Html.EditorFor(model => model.PhoneExt, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.PhoneExt, "", new { #class = "text-danger" })
</div>
</div>
#* Email *#
<div class="form-group">
#Html.LabelFor(model => model.Email, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-8">
#Html.EditorFor(model => model.Email, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Email, "", new { #class = "text-danger" })
</div>
</div>
#* SUBMIT *#
<div class="form-group">
<div class="col-md-offset-4 col-md-8">
<input type="submit" value="Create" class="btn btn-success" />
</div>
</div>
</div>
}
</div>
#Scripts.Render("~/Scripts/Custom/ajax-add-collection-item.js")
<script>
$(function () {
ajaxAddCollectionItem("new-contact-form", "contacts", function () {
alertify.success("Added new contact");
})
});
</script>
ajax-add-collection-item.js (capture modal form submission, add _CollectionItem.cshtml to main form)
// Posts form and adds collection item to ul
function ajaxAddCollectionItem(formId, listId, onSuccess = function () { }) {
let $form = $("#" + formId);
$form.submit(function (event) {
event.preventDefault();
$.ajax({
method: "POST",
url: $form.attr("action"),
data: $form.serialize(),
success: function (data) {
let successful = data["success"];
// If form is valid, close modal and append new entry to list
if (successful) {
$("#" + listId).append(data["html"]);
$(".delete-item").click(function (event) {
$(this).closest("li").remove();
});
$(".btn-modal-close").trigger("click");
onSuccess();
}
// If form is not valid, display error messages
else {
displayValidationErrors(data["errors"]);
}
},
error: function (error) {
alert("Dynamic content load failed.");
console.error("Ajax call failed for form: " + $form);
}
});
});
// Populate validation summary
function displayValidationErrors(errors) {
let $ul = $('div.validation-summary-valid.text-danger > ul');
$ul.empty();
$.each(errors, function (i, errorMessage) {
$ul.append('<li>' + errorMessage + '</li>');
});
}
}
ContactsController.cs
public class ContactsController
{
// GET: Contacts/CreateModal
public ActionResult CreateModal()
{
return PartialView("_CreateModal");
}
// POST: Contacts/CreateModal
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> CreateModal(ContactCreateViewModel viewModel)
{
// If form is valid and email does not already exist, send HTML for collection item,
// otherwise send modelstate errors
if (ModelState.IsValid)
{
User user = await UserManager.FindByEmailAsync(viewModel.Email);
if (user == null)
// RenderPartialView returns partial HTML as a string,
// see https://weblog.west-wind.com/posts/2012/May/30/Rendering-ASPNET-MVC-Views-to-String
return Json(new { success = true, html = RenderPartialView("_CollectionItem", viewModel) });
else
ModelState.AddModelError("Email", "Email already exists.");
}
return Json(new { success = false, errors = GetModelStateErrors() });
}
// Actually in base controller class
protected string[] GetModelStateErrors()
{
return ModelState.Values.SelectMany(x => x.Errors).Select(x => x.ErrorMessage).ToArray();
}
}

Related

Json Result isn't working when I use db.Entry(x).State = EntityState.Modified;

I Have a view where I can edit and add new Rows on my SQL called by AddOrEdit. All I need is to press the button Submit after fill/change the fields. It calls my ActionResult on AccountController that brings me a JsonResult and my AJAX function on button click get the JsonResult to fill a Notify.js message to say that the submit was successfully done.
Problem:
When I create a new row, all works how should be but when I update a existing row, the Success message comes to my browser as raw Json.
Controller:
[HttpPost]
public ActionResult AddOrEdit(UserPortal user)
{
using (ModelEntities db = new ModelEntities())
{
try
{
if (user.UserID == 0)
{
db.UserPortals.Add(user);
}
else
{
db.Entry(user).State = EntityState.Modified;
}
db.SaveChanges();
return Json(new { success = true, message = "Submitted Successfully. Redirecting..." }, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
return Json(new { success = true, message = ex.Message }, JsonRequestBehavior.AllowGet);
}
}
}
View:
#using (Html.BeginForm("AddOrEdit", "Account", FormMethod.Post, new { onsubmit = "return SubmitForm(this)" }))
{
<form id="AddOrEditUserForm">
#Html.HiddenFor(model => model.UserID)
<div class="form-group">
#Html.LabelFor(model => model.UserEmail, new { #class = "control-label" })
#Html.EditorFor(model => model.UserEmail, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.UserEmail)
</div>
<div class="form-group">
#Html.LabelFor(model => model.UserName, new { #class = "control-label" })
#Html.EditorFor(model => model.UserName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.UserName)
</div>
<div class="form-group">
#Html.LabelFor(model => model.UserCompany, new { #class = "control-label" })
#Html.EditorFor(model => model.UserCompany, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.UserCompany)
</div>
<div class="form-group">
#Html.LabelFor(model => model.UserPosition, new { #class = "control-label" })
#Html.EditorFor(model => model.UserPosition, new { htmlAttributes = new { #class = "form-control" } })
</div>
<div class="form-group">
#Html.LabelFor(model => model.UserAccessLevel, new { #class = "control-label" })
#Html.EditorFor(model => model.UserAccessLevel, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.UserAccessLevel)
</div>
<div class="form-group">
<input type="submit" name="Submit" value="Salvar" class="btn btn-primary" />
</div>
</form>
}
Javascript on View:
function SubmitForm(form) {
$.validator.unobtrusive.parse(form);
if ($(form).valid()) {
$.ajax({
type: "POST",
url: form.action,
data: $(form).serialize(),
success: function (data) {
var delay = 2000; // time in milliseconds
if (data.success) {
$.notify(data.message, {
globalPosition: "top center",
className: "success",
})
setTimeout(function () {
window.location.href = '#Url.Action("AdminUsers", "Account")'; //redirect to the main page after some seconds
}, delay);
}
},
error: function (jqXHR, textStatus, errorThrown) { errorFunction(); },
});
}
return false;
}
Notify.js working when I add a new user:
image 1
When I click on submit button to update a existing user
image 2
What I've tried:
1- I add some console.log on my Submit Function and after if ($(form).valid()) I just don't receive anymore my console.log test. I think the problem is the Function and the ajax inside it.
2- On controller I gave a single JsonResult for each situation: to create I had a message saying "Created Successfully" and It worked but on the message below "Update Successfully" I got the same problem: a raw json on my screen but working perfectly on backend updating the row I requested.

Edit Record using Partial View, JQuery and Bootstrap Modal

I have a table on which there's an Edit button for every record at the last column.
My goal is to have an editable form on a modal for the record on which the user pressed the Edit button.
In order to accomplish that, I've created a Partial View which i want to be loaded on the modal, but after tons of tries, i cannot get it working. The JS created to compose the partial view URL and loading into the modal seems to have no effect and it's raising the following error:
VM364 ESa31501901:361 Uncaught ReferenceError: ESa31501901 is not
defined
at HTMLAnchorElement.onclick
Note: ESa31501901 is the first parameter passed into the JS function.
This is my intention:
a) Edit() : This method will return all records.
b) EditClientFeature(string ClientID, string WorkProcessID): This method will return a partial view containing the record of a particular client. This method is called when we start editing a client record. The client record is displayed in modal (popup).
c) EditClientFeature(ClientFeatureViewModel model): This method will update the client record.
ClientFeature ViewModel
public class ClientFeatureViewModel
{
public string ClientID { get; set; }
public string WorkProcessID { get; set; }
public int? Certification { get; set; }
public bool? TrackingActive { get; set; }
public string ClientCode { get; set; }
public string ContractNo { get; set; }
public string ProductCode { get; set; }
}
Edit.cshtml
[...]
<tbody>
#foreach (var feature in Model.ClientFeatures)
{
<tr>
<td style="text-align:center"><strong>#feature.WorkProcessId</strong>/td>
<td style="text-align:center">#feature.Certificate</td>
<td style="text-align:center">#feature.TrackingActive</td>
<td style="text-align:center">#feature.ClientCode</td>
<td style="text-align:center">#feature.ContractNo</td>
<td style="text-align:center">#feature.ProductCode</td>
<td>
<i class="glyphicon glyphicon-pencil"></i>
</td>
</tr>
}
</tbody>
[...]
<div class="modal fade" id="ModalClientFeatures">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
×
<h3 class="modal-title">Edit</h3>
</div>
<div class="modal-body" id="ModalBodyDiv">
<!-- Here's where i want to show the partial view-->
</div>
</div>
</div>
</div>
[...]
<script>
function EditCF(ClientID, WorkProcessID) {
var url = "/Admin/EditClientFeature?ClientID=" + ClientID + "?WorkProcessID=" + WorkProcessID;
$("#ModalBodyDiv").load(url, function () {
$("#ModalClientFeatures").modal("show");
})
}
</script>
ClientFeaturepartialView.cshtml
#model Project.Models.ClientFeatureViewModel
<script src="~/Scripts/jquery-3.3.1.js"></script>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<form id="myForm">
<div class="form-horizontal">
<h4>ClientFeatureViewModel</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.ClientID)
<div class="form-group">
#Html.LabelFor(model => model.WorkProcessID, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.WorkProcessID, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.WorkProcessID, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Certification, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Certification, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Certification, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.TrackingActive, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
#Html.EditorFor(model => model.TrackingActive)
#Html.ValidationMessageFor(model => model.TrackingActive, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ClientCode, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ClientCode, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ClientCode, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ContractNo, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ContractNo, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ContractNo, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ProductCode, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ProductCode, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ProductCode, "", 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" />
<a href="#" id="btnSubmit" class="btn btn-success btn-block">
<span>Update</span>
</a>
</div>
</div>
</div>
</form>
}
Controller
public ActionResult EditClientFeature(string ClientID, string WorkProcessID)
{
PMEntities db = new EntityConn().Db;
ClientFeatures ClientFeature = db.ClientFeatures.Where(cf => cf.ClientId == ClientID && cf.WorkProcessId == WorkProcessID).SingleOrDefault();
if (ClientFeature != null) {
ClientFeatureViewModel model = new ClientFeatureViewModel
{
ClientID = ClientFeature.ClientId,
WorkProcessID = ClientFeature.WorkProcessId,
Certification = ClientFeature.Certificate,
TrackingActive = ClientFeature.TrackingActive,
ClientCode = ClientFeature.ClientCode,
ContractNo = ClientFeature.ContractNo,
ProductCode = ClientFeature.ProductCode,
};
return PartialView("ClientFeaturePartialView", model);
}
else { return View("Error"); }
}
[HttpPost]
public ActionResult EditClientFeature(ClientFeatureViewModel model)
{
try
{
PMEntities db = new EntityConn().Db;
if (model.ClientID != null)
{
//update
ClientFeatures ClientFeature = db.ClientFeatures.Where(cf => cf.ClientId == model.ClientID && cf.WorkProcessId == model.WorkProcessID).SingleOrDefault();
ClientFeature.Certificate = model.Certification;
ClientFeature.ClientCode = model.ClientCode;
ClientFeature.ContractNo = model.ContractNo;
ClientFeature.ProductCode = model.ProductCode;
ClientFeature.TrackingActive = model.TrackingActive;
db.SaveChanges();
}
}
catch (Exception ex)
{
throw ex;
}
}
I think your onclick function parameter value is treated as a variable, not a string.
Solution 1:
Try below to pass as string: (Not tested though!)
onclick="EditCF(\'' + #Model.Piva + '\', \'' + #feature.WorkProcessId+ '\')"
Solution 2:
It's best to Attach a click handler after adding a class for your link. And use HTML5 data attributes for storing your value client side.
<i class="glyphicon glyphicon-pencil"></i>
$('.editClient).on('click', function() {
var clientID = $(this).data('ClientID');
var workProcessId = $(this).data('WorkProcessId');
var url = "/Admin/EditClientFeature?ClientID=" + clientID
+ "?WorkProcessID=" + workProcessID;
$("#ModalBodyDiv").load(url, function () {
$("#ModalClientFeatures").modal("show");
})
});
Reference
Hope this helps.

If checkbox is checked then enable EditorFor

I would like my Checkbox to disable EditorsFor if it is unchecked and enable them if it is checked. I know I have to use JavaScript, I found some codes in net, but it seems that they don't work.
Here is my View code:
#{Html.RenderPartial("_PartialError");}
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
(...)
<div class="form-group">
#Html.LabelFor(model => model.Czy_zuzywalny, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
#Html.EditorFor(model => model.Czy_zuzywalny)
#Html.ValidationMessageFor(model => model.Czy_zuzywalny, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Ilosc_minimalna, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Ilosc_minimalna, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Ilosc_minimalna, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Ilosc_optymalna, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Ilosc_optymalna, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Ilosc_optymalna, "", new { #class = "text-danger" })
</div>
</div>
(...)
}
And I wrote something like this and put in js file (ofc at the end of this code is ), but it doesn't work...
$(document).ready(function ()
{
$("#Czy_zuzywalny").click(function ()
{
if ($("#Ilosc_minimalna").attr("disabled") == "")
{
$("#Ilosc_minimalna").attr("disabled", "disabled");
$("#Ilosc_optymalna").attr("disabled", "disabled");
$("#Ilosc_minimalna").attr("value", "0");
$("#Ilosc_optymalna").attr("value", "0");
}
else
{
$("#Ilosc_minimalna").attr("disabled", "");
$("#Ilosc_optymalna").attr("disabled", "");
}
});
});
Nothing happens even if I check or uncheck my checkbox. Can anyone help me with that?
Change your jQuery code to:
$(document).ready(function () {
$("#Czy_zuzywalny").click(function () {
if ($("#Ilosc_minimalna").is('[disabled=disabled]')) {
$("#Ilosc_minimalna").removeAttr("disabled");
$("#Ilosc_optymalna").removeAttr("disabled");
}
else {
$("#Ilosc_minimalna").attr("disabled", "disabled");
$("#Ilosc_optymalna").attr("disabled", "disabled");
$("#Ilosc_minimalna").attr("value", "0");
$("#Ilosc_optymalna").attr("value", "0");
}
});
});
The if condition on your code never actually evaluates to true because in an enabled input, the 'disabled' attribute doesn't have a value of an empty string. it just doesn't exist (thus the use of removeAttr("disabled")).
UPDATE: Working JSFiddle here
UPDATE 2:
In order to add the script in the Create view and have it show after the jQuery script tag in the rendered HTML do this:
First add a call to RenderSection in your Layout file just before the closing </body> tag like this:
#RenderSection("scripts", required: false)
This will give you the ability to include a 'scripts' section in your views, the contents of which, will appear instead of the RenderSection call in the final HTML. Note that the required: false parameter specifies that you don't have to include this section in every view.
Then in your Create view, outside of any section add this:
#section scripts {
<script src="/scripts/CheckBoxItemCreate.js"></script>
}
Hope this helps!

Validation in jquery for bootstrap popup

Here is my View:
#using (Html.BeginForm("SaveNewCustomer", "Dealer", FormMethod.Post, new { id = "myForm" }))
{
<div class="form-horizontal">
<div class="row">
<div class="form-group-1">
#Html.LabelFor(model => model.device.MotorType, htmlAttributes: new { #class = "control-label col-lg-4" })
#Html.EditorFor(model => model.device.MotorType, new { htmlAttributes = new { #class = "form-control required", placeholder = "Motor Type", required = "required" } })
</div>
<div class="form-group-1">
#Html.LabelFor(model => model.device.PowerRating, htmlAttributes: new { #class = "control-label col-lg-4" })
#Html.EditorFor(model => model.device.PowerRating, new { htmlAttributes = new { #class = "form-control required", placeholder = "Power Rating", required = "required" } })
</div>
<div class="form-group-1">
#Html.LabelFor(model => model.device.InstallationDate, htmlAttributes: new { #class = "control-label col-lg-4" })
#Html.EditorFor(model => model.device.InstallationDate, new { htmlAttributes = new { #class = "form-control datepicker required", placeholder = "Installation Date(MM/dd/yyyy)", required = "required" } })
</div>
<div class="form-group-1">
#Html.LabelFor(model => model.device.ActivationDate, htmlAttributes: new { #class = "control-label col-lg-4" })
#Html.EditorFor(model => model.device.ActivationDate, new { htmlAttributes = new { #class = "form-control datepicker required", placeholder = "Activation Date(MM/dd/yyyy)", required = "required" } })
</div>
<div class="form-group-1">
#Html.LabelFor(model => model.device.DataReceiveInterval, htmlAttributes: new { #class = "control-label col-lg-4" })
#Html.EditorFor(model => model.device.DataReceiveInterval, new { htmlAttributes = new { #class = "form-control required", placeholder = "Data receive Interval", required = "required" } })
</div>
<div class="form-group-1">
#Html.LabelFor(model => model.device.HasAMC, htmlAttributes: new { #class = "control-label col-lg-4" })
#Html.EditorFor(model => model.device.HasAMC, new { htmlAttributes = new { #class = "form-control required", #onchange = "OnChange();" } })
</div>
<div class="form-group-1" id="HasDate">
#Html.LabelFor(model => model.device.AMCExpiredDate, htmlAttributes: new { #class = "control-label col-lg-4" })
#Html.EditorFor(model => model.device.AMCExpiredDate, new { htmlAttributes = new { #class = "form-control required", placeholder = "AMCExpireDate(MM/dd/yyyy)", required = "required", title = "Enter AMC Expire Date" } })
</div>
<button style="margin-left:33%;" id="action" class="btn btn-sm btn-primary col-lg-2 " type="button" name="action" value="SaveDeviceInfo"><strong>Save</strong></button>
</div>
</div>
}
My javascript script is
<script type="text/javascript">
$(document).ready(function () {
jQuery.validator.setDefaults({
debug: true,
success: "valid"
});
$( "#myForm" ).validate({
rules: {
"client.ContactNo": {
required: true
}
}
});
$("#action").click(function () {
if (!$("#myForm").validate()) { // Not Valid
return false;
} else {
Save();
}
});
function Save() {
var frm = $("#myForm").serialize();
$.ajax({
url: "/Dealer/SaveNewCustomer",
data: frm,
type: "POST",
success: function (result) {
if (result == "true") {
//alert(result);
window.location.href = "/Dealer/Customers?Success=true&Message=Customer updated successfully.";
}
else
toastr.error(result);
}
});
}
</script>
Problem is Validation not fire. In If else condition it is showing false and direct store the value in database. Could you please help me?
Is anything wrong in my code? Give me suggestions please.
Thanks in advance.
.validate() is only the initialization method.
.valid() is the method used for testing the form.
if (!$("#myForm").valid()) { ....
It's a moot point because your .ajax() function belongs inside the submitHandler option of the plugin anyway. The submitHandler callback only fires when the form is valid, thereby you can entirely eliminate your whole if/then click handler function (however you must change the button element into a type="submit").
$(document).ready(function () {
jQuery.validator.setDefaults({
debug: true,
success: "valid"
});
$( "#myForm" ).validate({
rules: {
"client.ContactNo": {
required: true
}
},
submitHandler: function(form) { // only fires when form is valid
var frm = $(form).serialize();
$.ajax({
url: "/Dealer/SaveNewCustomer",
data: frm,
type: "POST",
success: function (result) {
if (result == "true") {
//alert(result);
window.location.href = "/Dealer/Customers?Success=true&Message=Customer updated successfully.";
}
else
toastr.error(result);
}
});
return false;
}
});
});
NOTE: If you happen to be using the unobtrusive-validation plugin as included within your ASP framework, then the .validate() method is constructed and called automatically. If that's the case, then your call to .validate() will be ignored, and you would put any plugin options only within jQuery.validator.setDefaults().
You are missing your form tags from your html. Also, you dont have anything with the id of myform. So your trying to validate #myform in your jquery but there is no myform. You would need to add your form tags and give it an id of myform.

Display Custom Errors in Html.ValidationMessageFor via jQuery

My ASP.NET MVC 5 application's razor view uses two checkboxes:
<div class="form-group">
#Html.LabelFor(model => model.BoolField1, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
#Html.EditorFor(model => model.BoolField1, new { htmlAttributes = new { #class = "form-control", #id = "bool1" } })
#Html.ValidationMessageFor(model => model.BoolField1, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.BoolField2, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
#Html.EditorFor(model => model.BoolField2, new { htmlAttributes = new { #class = "form-control", #id = "bool2" } })
#Html.ValidationMessageFor(model => model.BoolField2, "", new { #class = "text-danger" })
</div>
</div>
</div>
I'm trying implement the rule that BoolField2 cannot be true unless BoolField1 is also true. My jquery code:
function applyRule() {
var bool1Status = document.getElementById('bool1').checked;
var bool2Status = document.getElementById('bool2').checked;
if (bool2Status == true && bool1Status == false) {
// This is the sole error.
// Generate a suitable error message and display (how?)
}
}
The custom error generated at this code must be displayed into Html.ValidationMessageFor. How can I achieve this?
First you need to correct syntax for EditorFor () it should be like following
#Html.EditorFor(model => model.BoolField1, new { #class = "form-control", #id = "bool1" })
instead of
#Html.EditorFor(model => model.BoolField1, new { htmlAttributes = new { #class = "form-control", #id = "bool1" } })
Now after having this correction you may write custom jQuery logic to achieve same. Here is the code.
$(function () {
$('#bool2').on('click', function (e) {
//Get the state of 1st checkbox
var isFirstCheck = $('#bool1').is(":checked");
if (isFirstCheck==false) {
//dispay message if you need. Below line of code will prevent user to select 2nd checkbox
e.preventDefault();
}
})
});

Categories

Resources