Ignore Model validation in HTML form - javascript

Here's my setup
HTML
#using (Html.BeginForm("Action", "Controller", FormMethod.Post, new { #class = "form-horizontal", role = "form", enctype = "multipart/form-data", id = "mainForm" }))
{
<div class="form-group">
#Html.LabelForRequired(m => m.Prop1)
#Html.DropDownListFor(m => m.Prop1, (SelectList)ViewBag.SelectList, "Select Role...", new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Prop1, null, new { #class = "help-block" })
</div>
<div class="row">
<div class="col-sm-2 pull-right">
<button type="submit" class="btn btn-default" id="previous">#Html.T("Back")</button>
<button type="submit" class="btn btn-primary">#Html.T(Model.ButtonText)</button>
</div>
</div>
}
View Model Setup
public class ViewModel{
[Required]
public string Prop1 { get; set;}
}
What I am trying to achieve is that when I hit the back button, I want to ignore any form validation and just redirect the user to my post back action in the controller.
Here's what my JavaScript looks like
$("#previous").off('click').on('click', (evt) => {
var form = $("#mainForm");
if (form.length != 0) {
this.resetFormValidation(form);
}
var actionUrl = $('#mainForm').attr('action');
var indexOfBackslash = actionUrl.lastIndexOf('/');
var newActionUrl = actionUrl.slice(0, indexOfBackslash + 1);
var newActionUrl = newActionUrl + 'BackSubmit';
$('#mainForm').attr('action', newActionUrl);
(<any>$('#mainForm').validate()).cancelSubmit = true;
if (form.length != 0) {
this.resetFormValidation(form);
}
});
}
resetFormValidation(form: any) {
$("#mainForm").find('[data-valmsg-replace]')
.removeClass('field-validation-error')
.addClass('field-validation-valid')
.empty();
$("#mainForm").find('div.has-error').removeClass('has-error');
}
This still shows the field validation and does not go through with the post-back. What am I missing?

Related

C# asp.net mvc Set CheckBoxFor checked-property with Model-Value

In my form i have a chekbox and when i click the checkbox a textbox is enabled.
When i submit the form i got both values(checkbox and textbox)and the site refresh,after the refresh the checkbox is checked but the textbox is disabled but has the last insert value.
If i submit again without making something the textbox returns null and not the last insert value.
I want that the checkbox got the value from my model and change the behavior of the textbox disabled-property und if no new value will be insert,it should return the last insert value.
When i set the model property of false the checkbox is also checked.
Has anyone a idea what i can do ?
View:
#Html.TextBoxFor(m => m.FilterModel.FilterOrgNameValue, new { #class = "form-control", #id = "OrganisatioName", #disabled = "disabled" })
#Html.CheckBoxFor(m => m.FilterModel.FilterOrgNameIsCheckedValue, new { #class = "form-control", #id = "OrgNameChecked", #checked = (Model.FilterModel.FilterOrgNameIsCheckedValue ? "checked" : "unchecked")})
JavaScript:
$("#OrgNameChecked").click(function () {
$('#OrganisatioName').attr("disabled", $(this).is(':unchecked'));
});
Model:
public bool FilterOrgNameIsCheckedValue { get; set; }
Controller (Function which got called by submit):
public ActionResult Index(AdminOrganizationModel m)
{
AdminOrganizationModel model = new AdminOrganizationModel();
if(TempData["model"] != null)
{
m = (AdminOrganizationModel)TempData["model"];
}
if(m.FilterModel == null)
{
m.FilterModel = new AdminOrganizationFilterModel();
}
model = m;
OrganizationBusinessObject organizationBusinessObject = new OrganizationBusinessObject(DbContext);
var organizations = DbContext.GetAllEntitiesQueryable<Organization>();
organizations = FilterOrganizations(organizations, model);
InitializeLicenseList(1);
AdminOrganizationModelBuilder modelBuilder = new AdminOrganizationModelBuilder();
IList<AdminOrganizationModel> organizationsModels = modelBuilder.GetModelCollection(organizations);
model.Organizations = new AjaxGridFactory().CreateAjaxGrid(organizationsModels.AsQueryable(), 1, false, 10) as AjaxGrid<AdminOrganizationModel>;
return View(model);
}
Fields after submit
Simple Solution ;)
I added a simple if statement in the View:
<div class="col-sm-2">
#if (Model.FilterModel.FilterOrgNameIsCheckedValue)
{
#Html.TextBoxFor(m => m.FilterModel.FilterOrgNameValue, new { #class = "form-control", #id = "OrganisatioName"})
}
else
{
#Html.TextBoxFor(m => m.FilterModel.FilterOrgNameValue, new { #class = "form-control", #id = "OrganisatioName", #disabled = "disabled" })
}
</div>
I guess its not the best way but it works =)

2nd dropdown not displaying after selecting the value from 2nd dropdown in asp.net mvc

I am using cascading dropdownlist in asp.net mvc.
When a value is selected from the first dropdown, the list is shown in 2nd dropdown. When I select the value from the 2nd dropdown it shows in the dropdown, but after clicking the submit button it disappears showing "Select from List". Why?
View:
<div class="row form-group">
<div class="col-md-6">
#Html.LabelFor(model => model.Religion_Id, new { #class = "control-label" })
<div class="input-group">
<span class="input-group-addon" style="background:white">
<i class="fa fa-cloud" style="color:#179CDC;"></i>
</span>
#Html.DropDownListFor(model => model.Religion_Id, Model.Religion, "Select From List", new { #class = "form-control select2me", #id = "ddlReligion" })
</div>
#Html.ValidationMessageFor(model => model.Religion_Id, string.Empty, new { #class = "small text-danger text-uppercase" })
</div>
<div class="col-md-6">
#Html.LabelFor(model => model.Sect_Id, new { #class = "control-label" })
<div class="input-group">
<span class="input-group-addon" style="background:white">
<i class="fa fa-cloud" style="color:#179CDC;"></i>
</span>
<div id="Sects">
#Html.DropDownListFor(model => model.Sect_Id, new List<SelectListItem>(), "Select Form List", new { #class = "form-control select2me", #id = "ddlSect" })
</div>
</div>
#Html.ValidationMessageFor(model => model.Sect_Id, string.Empty, new { #class = "small text-danger text-uppercase" })
</div>
</div>
<script>
$(document).ready(function () {
loadSect();
});
var loadSect = function (flag) {
if ("undefined" == typeof (flag)) {
flag = true;
}
$.ajax({
type: "post",
url: '#Url.Action("GetSects", "MyProfile", new { area = "Candidate" })',
data: { religionId: $('#ddlReligion').val() },
datatype: "json",
traditional: true,
success: function (data) {
var district = "<select id='ddlSect' class='form-control text-uppercase select2me' name='Sect_Id'>";
district = district + '<option value="">Select From List</option>';
for (var i = 0; i < data.length; i++) {
district = district + '<option value=' + data[i].Value + '>' + data[i].Text + '</option>';
}
district = district + '</select>';
$('#Sects').html(district);
if (flag) {
setOption($('#Sects select')[0], $('#HSPEC_ID').val())
}
if (jQuery().select2) {
$('#Sects .select2me').select2({
placeholder: "Select an option",
allowClear: true
});
}
}
});
};
$('#ddlReligion').change(function () {
loadSect(false);
});
function setOption(selectElement, value) {
var options = selectElement.options;
for (var i = 0, optionsLength = options.length; i < optionsLength; i++) {
if (options[i].value == value) {
selectElement.selectedIndex = i;
return true;
}
}
return false;
}
You are not doing a ajax submit. OR Your are not setting the value of second drop down back after post
In your code, I don't see any ajax submit after you choose the second drop dwn and hit submit. So the problem is you are posting this form to controller and then the controller is returning the view back with the same posted data. Now in the Razor syntax for the second drop down you are using
#Html.DropDownListFor(model => model.Sect_Id, new List<SelectListItem>(), "Select Form List", new { #class = "form-control select2me", #id = "ddlSect" })
Here you can see you are setting the value of second drop down by empty list new List<SelectListItem>() and that is why the second drop down is empty.
Solution
Either use AJAX submit for your form. So that your UI remains unchanged.
Change your Razor syntax to this
#Html.DropDownListFor(model => model.Sect_Id, Model.District, "Select Form List", new { #class = "form-control select2me", #id = "ddlSect" })
So add a additional property called Districts and initially set this Model.District to be new List<SelectListItem>() and then in your form post method you just pass back the data as received and it will be rendered properly after submit.

how to pass multiple values from Html Action Link control capturing from user entered text box and send to Action method?

I have the following View:
<div class="form-group">
#Html.LabelFor(m => m.LoginId, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.LoginId, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.LoginId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.Password, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.PasswordFor(m => m.Password, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Password, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
#Html.ActionLink("Log in", "Login1", null, new { #class = "link" })
</div>
</div>
And this the javascript:
$(function () {
$('.link').click(function () {
var loginid = $("#LoginId").val();
var pass = $("#Password").val();
this.href = this.href + '?loginid=' + encodeURIComponent(loginid);
this.href = this.href + '?password=' + encodeURIComponent(pass); // Something is going wrong here!
});
});
And this is the Controller Action method:
public ActionResult Login1(string loginid,string password)
{
if (loginid == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
User user = db.Users.Find(loginid);
if (user == null)
{
return HttpNotFound();
}
return RedirectToAction("Index", "Products");
}
I have entered loginid=a and password=b.
But the problem is:it is sending the loginid =:a?password=b and password=null.
How can I send the parameter properly?
make the button to submit button and the form will post automatically on click you wont have to write any other code.
make sure that your textbox names(not ids) matches the parameter names in your action.
I think, and i'm no pro, that the error is in the ajax function. The '?' is causing the problem. Current is as follows:
this.href = this.href + '?loginid=' + encodeURIComponent(loginid);
this.href = this.href + '?password=' + encodeURIComponent(pass);
But should rather be:
this.href = this.href + '?loginid=' + encodeURIComponent(loginid);
this.href = this.href + '&password=' + encodeURIComponent(pass);

Dropdownlist onchanged - Trouble persisting ViewModel

I am a ASP.NET developer that is trying to get to grips with MVC.
I'm creating a register page and I have 3 dropdowns.
Now the first dropdown must load first go to load the countries. Based on that I load the provinces and then based on that I load the cities in that province.
The trouble I'm having is that on the first change it keeps my selected value but on the second onchange it seems as everything is lost.
I load the reigster view by just loading countries so long. then the javascript posts it to an action.
cshtml
<label class="col-md-3 col-xs-5 control-label">Country:</label>
<div class="col-md-9 col-xs-7">
#Html.DropDownListFor(x => x.CountryId, (IEnumerable<SelectListItem>)ViewBag.CountryItems, "Please Select", new { #class = "form-control select", #onchange = "CallChangefunc(this.value, null)" })
</div>
</div>
<div class="form-group">
<label class="col-md-3 col-xs-5 control-label">Province:</label>
<div class="col-md-9 col-xs-7">
#Html.DropDownListFor(x => x.ProvinceId, (IEnumerable<SelectListItem>)ViewBag.ProvinceItems, "Please Select", new { #class = "form-control select", #onchange = "CallChangefunc(null, this.value)" })
</div>
</div>
<div class="form-group">
<label class="col-md-3 col-xs-5 control-label">City:</label>
<div class="col-md-9 col-xs-7">
#Html.DropDownListFor(x => x.CityId, (IEnumerable<SelectListItem>)ViewBag.CityItems, "Please Select", new { #class = "form-control select" })
</div>
</div>
The javascript
function CallChangefunc(countryId, provinceId) {
window.location.href = "/Master/SetDropDowns?provinceId=" + provinceId + "&countryId=" + countryId ;
}
First one "Register" loads 1'st then SetDropDowns gets called onchanged.
I load the viewbags(SelectedItemLists) otherwise I get errors on refresh. is there a better way to code the viewbags to not have in two places?
[HttpGet]
public ActionResult Register()
{
IEnumerable<SelectListItem> CountryItems = BusinessAPI.CountryManager.GetAllCountries().Select(ci => new SelectListItem
{
Value = ci.Id.ToString(),
Text = ci.Name
});
ViewBag.CountryItems = CountryItems;
IEnumerable<SelectListItem> ProvinceItems = BusinessAPI.ProvinceManager.GetAllProvincesByCountryId(0).Select(ci => new SelectListItem
{
Value = ci.Id.ToString(),
Text = ci.Name
});
ViewBag.ProvinceItems = ProvinceItems;
IEnumerable<SelectListItem> CityItems = BusinessAPI.CityManager.GetAllCitiesByProvinceId(0).Select(ci => new SelectListItem
{
Value = ci.Id.ToString(),
Text = ci.Name
});
ViewBag.CityItems = CityItems;
return View();
}
public ActionResult SetDropDowns(string provinceId, string countryId)
{
IEnumerable<SelectListItem> CountryItems = BusinessAPI.CountryManager.GetAllCountries().Select(ci => new SelectListItem
{
Value = ci.Id.ToString(),
Text = ci.Name
});
ViewBag.CountryItems = CountryItems;
int countId = 0;
if (countryId == "null")
countryId = string.Empty;
if (TempData["CountryId"] == null)
{
if (!string.IsNullOrEmpty(countryId))
{
countId = Convert.ToInt32(countryId);
TempData["CountryId"] = countId;
}
}
else
countId = Convert.ToInt32(TempData["ProvinceId"]);
IEnumerable<SelectListItem> ProvinceItems = BusinessAPI.ProvinceManager.GetAllProvincesByCountryId(Convert.ToInt32(countId)).Select(ci => new SelectListItem
{
Value = ci.Id.ToString(),
Text = ci.Name
});
ViewBag.ProvinceItems = ProvinceItems;
int provId = 0;
if (provinceId == "null")
provinceId = string.Empty;
if (TempData["ProvinceId"] == null)
{
if (!string.IsNullOrEmpty(provinceId))
{
provId = Convert.ToInt32(provinceId);
TempData["ProvinceId"] = provId;
}
}
else
provId = Convert.ToInt32(TempData["ProvinceId"]);
IEnumerable<SelectListItem> CityItems = BusinessAPI.CityManager.GetAllCitiesByProvinceId(provId).Select(ci => new SelectListItem
{
Value = ci.Id.ToString(),
Text = ci.Name
});
ViewBag.CityItems = CityItems;
return View("Register");
}
The problem is that you don't tell them to be selected, modify your lists that have SelectListItem like the example below, to tell what item from list is Selected.
IEnumerable<SelectListItem> CountryItems = BusinessAPI.CountryManager.GetAllCountries().Select(ci => new SelectListItem
{
Value = ci.Id.ToString(),
Text = ci.Name,
Selected = ci.id.ToString() == countryId // if match the condition is selected
});
Also, to keep both listed selected you can modify your View.
Modify the javascript function to send always the countryId. Doing this the current country will be always selected, even when you change province.
function CallChangefunc(provinceId) {
var countries = document.getElementById("CountryId");
var countryId = countries.options[countries.selectedIndex].value;
window.location.href = "/Master/SetDropDowns?provinceId=" + provinceId + "&countryId=" + countryId ;
}
Notice that on first dropdown CallChangefunc(null), with this we tell that we don't have a province selected, which is true.
<div class="col-md-9 col-xs-7">
#Html.DropDownListFor(x => x.CountryId, (IEnumerable<SelectListItem>)ViewBag.CountryItems, "Please Select", new { #class = "form-control select", #onchange = "CallChangefunc(null)" })
</div>
On second dropdown we send CallChangefunc(this.value), with this we tell what province was selected to take cities and to keep the current value selected after postback. And because the countryId is always send it will remain unchanged.
<div class="col-md-9 col-xs-7">
#Html.DropDownListFor(x => x.ProvinceId, (IEnumerable<SelectListItem>)ViewBag.ProvinceItems, "Please Select", new { #class = "form-control select", #onchange = "CallChangefunc(this.value)" })
</div>

MVC5: Posting JSON via Ajax not correctly passing data to Controller?

I am attempting to do some duplication checking in my MVC5/EF Code-First application. On my Create() Asset View, I show/hide textboxes for entering a new location_dept/location_room via JS:
<div class="form-group">
#*#Html.LabelFor(model => model.Location_Id, "Location_Id", htmlAttributes: new { #class = "control-label col-md-2" })*#
<span class="control-label col-md-2">Location:</span>
<div class="col-md-4">
#*#Html.DropDownList("Location_Id", null, htmlAttributes: new { #class = "form-control dropdown" })*#
#Html.DropDownListFor(model => model.Location_Id, (SelectList)ViewBag.Model_List, htmlAttributes: new { #class = "form-control dropdown", #id = "selectLocation" })
#Html.ValidationMessageFor(model => model.Location_Id, "", new { #class = "text-danger" })
</div>
<div class="col-md-2">
<div class="btn-group">
<button id="createNewLocation" type="button" class="btn btn-success" aria-expanded="false">CREATE NEW</button>
</div>
</div>
<div class="col-md-4">
<div id="createLocationFormContainer" style="display:none">
<form action="/createNewLocation">
<input type="text" id="textNewLocationDept" name="location_dept" placeholder="New Department" />
<input type="button" id="submitNewLocation" value="Submit" />
<input type="button" id="cancelNewLocation" value="Cancel" /><br />
<input type="text" id="textNewLocationRoom" name="location_room" placeholder="New Room" />
</form>
</div>
</div>
</div>
JS:
$('#createNewLocation').click(function () {
$('#createLocationFormContainer').show();
})
$('#cancelNewLocation').click(function () {
$('#createLocationFormContainer').hide();
})
$('#submitNewLocation').click(function () {
var form = $(this).closest('form');
var data = { location_dept: document.getElementById('textNewLocationDept').value, location_room: document.getElementById('textNewLocationRoom').value };
// CORRECTLY SHOWING
alert("Dept: " + data.location_dept + " | Room: " + data.location_room);
$.ajax({
type: "POST",
dataType: "JSON",
url: '#Url.Action("createNewLocation", "INV_Assets")',
data: data,
success: function (resp) {
if (resp.LocationRoomExists)
{
alert("Room Location [" + resp.Text + "] already exists. Please select from the DropDown.");
} else {
// FALSE
alert("LocationRoomExists: " + resp.LocationRoomExists);
// `undefined` returned for both values
alert("Department: " + resp.location_dept + " | Room: " + resp.location_room);
$ $('#selectLocation').append($('<option></option>').val(resp.ID).text(resp.LocDept + "| " + resp.LocRoom));
$('#createLocationFormContainer').hide();
var count = $('#selectLocation option').size();
$("#selectLocation").prop('selectedIndex', count - 1);
}
},
error: function () {
alert("ERROR - Something went wrong adding new Room Location [" + resp.Text + "]!");
$('#createLocationFormContainer').hide();
}
});
});
I then use a JSON POST to my controller action to create the new INV_Location:
[HttpPost]
public JsonResult createNewLocation(string department, string room)
{
INV_Locations location = new INV_Locations()
{
// ID auto-set during save.
location_dept = department,
location_room = room,
created_date = DateTime.Now,
created_by = System.Environment.UserName
};
var duplicateLocation = db.INV_Locations.FirstOrDefault(x => x.location_room.ToUpper() == location.location_room.ToUpper());
try
{
if (duplicateLocation == null)
{
if (ModelState.IsValid)
{
db.INV_Locations.Add(location);
db.SaveChanges();
}
}
else
{
location = duplicateLocation;
}
}
catch (Exception ex)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}
return Json(new { ID = location.Id, LocDept = location.location_dept, LocRoom = location.location_room, LocationRoomExists = (duplicateLocation != null) }, JsonRequestBehavior.AllowGet);
}
When I run the code all together, I get a result in my dropdown of undefined|undefined. After some debugging I determined that my controller is not receiving a department/room value (null).
Can anyone spot what might be going wrong with my AJAX call to my controller?
EDIT:
$('#selectLocation').append($('<option></option>').val(resp.ID).text(resp.LocDept + "| " + resp.LocRoom));
You need to make sure your parameters match that you are sending:
var data = { department: document.getElementById('textNewLocationDept').value, room: document.getElementById('textNewLocationRoom').value };
You also need to match the data that you are returning from your controller.
Your action returns this:
new { ID = location.Id, LocDept = location.location_dept,
LocRoom = location.location_room,
LocationRoomExists = (duplicateLocation != null) }
So your bind needs to match the properties i.e.
$('#selectLocation').append($('<option></option>')
.val(resp.Id).text(resp.LocRoom + "| " + resp.LocDept ));

Categories