I need to be able to require certain fields if someone selects a value of "Yes" from a dropdown. I've used the following code but it doesn't seem to work.
$(function () {
$('#anyAdditionalInc').keyup(function () {
if ($(this).val() == "No") {
$('#additionalIncomeSource').removeAttr('required');
$('#additionalIncomeAmt').removeAttr('required');
} else {
$('#additionalIncomeSource').attr('required', 'required');
$('#additionalIncomeAmt').attr('required', 'required');
}
});
});
My dropdown looks like this
<div class="form-group">#Html.LabelFor(m => m.anyAdditionalInc, new { #class = "col-sm-2 control-label" })
<div class="col-sm-10">
<div class="col-sm-4">#Html.DropDownListFor(m => m.anyAdditionalInc, new SelectList(new List
<Object>{ new { value = "", text = "----"}, new { value = "Yes", text = "Yes"}, new { value = "No", text = "No"}, }, "value", "text"), new { #class = "form-control", id = "anyAdditionalInc" }) #Html.ValidationMessageFor(m => m.anyAdditionalInc)</div>
</div>
</div>
Any help is appreciated. It doesnt seem to want to require the validation on the source and amt fields when selecting yes.
A dropdown (I guess you mean a <select> element by that) doesn't have much keyup events. Try change instead:
$(function () {
$('#anyAdditionalInc').change(function () {
var active = $(this).val() != "No"),
fields = $('#additionalIncomeSource, #additionalIncomeAmt');
fields.prop('required', active);
if (!active) fields.val("");
});
});
Even though #Bergi answered the question from a client-side perspective, since you tagged the question asp.net-mvc-4 I presume you may wish to know how it's done on the server side (where it really matters!):
You can simply check it in your controller:
public ActionResult Foo(SomeModel someModel) {
if (someModel.anyAdditionalInc != "Yes") {
ModelState.AddModelError("", "You must select yes");
}
}
Or if you want to push the logic into your model itself:
public class SomeModel: IValidatableObject {
public string anyAdditionalInc {get; set;}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (this.anyAdditionalInc != "Yes") {
yield return new ValidationResult("You must select yes");
}
}
}
Notice how the model:
Implements IValidateableObject
Has a method named Validate which returns the type IEnumerable<ValidationResult>
During the model binding process this method will automatically be called and if a validation result is returned your ModelState will no longer be valid. So using this familiar code in your controller will make sure you don't take any action unless your custom conditions check out:
public class SomeController {
public ActionResult SomeAction() {
if (ModelState.IsValid) {
//Do your stuff!
}
}
}
Related
cshtml code for one of the textboxes. I'm trying to trigger a function on form submit that checks whether there's anything typed in the textboxes. If there isn't anything typed in the textboxes, the border should turn red.
#model WebForum.Models.AccountViewModel
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="~/Scripts/Custom.js"></script>
</head>
<h2 style="font-size:larger">CreateAccount</h2>
<p style="font-size:large">Please enter BOTH an account name and a password.</p>
<div id="account_create">
#using (Html.BeginForm("AccountCreated", "Home", FormMethod.Post, new { #id = "accountform" }, ))
{
#Html.TextBoxFor(Model => Model.Account_Name, new { #id = "account_name", #placeholder = "Your Account Name" })
<br />
<br />
#Html.TextBoxFor(Model => Model.Password, new { #id = "account_password", #placeholder = "Type Password Name" })
<br />
<br />
#Html.ValidationMessageFor(m => Model.Account_Name)
#Html.ValidationMessageFor(m => Model.Password)
<form id="accountform" onsubmit="accountform()">
<input type='submit' id="accountform" name="Create Account">
</form>
}
</div>
Heres the javascript file. The function should be triggered on ="onsubmit". I've tried various forms of .onsubmit, but they've haven't worked.
//run on form submit
function loginform() {
if ($('#account_name').val() == '') {
$('#account_name').css('border-color', 'red');
}
else {
$('#account_name').css('border-color', '');
}
if ($('#account_password').val() == '') {
$('#account_password').css('border-color', 'red');
}
else {
$('#account_password').css('border-color', '');
}
};
function accountform() {
if ($('#account_name').val() == '') {
$('#account_name').css('border-color', 'red');
}
else {
$('#account_name').css('border-color', '');
}
if ($('#account_password').val() == '') {
$('#account_password').css('border-color', 'red');
}
else {
$('#account_password').css('border-color', '');
}
};
function postform() {
if ($('#poster_name').val() == '') {
$('#poster_name').css('border-color', 'red');
}
else {
$('#poster_name').css('border-color', '');
}
if ($('#poster_text').val() == '') {
$('#poster_text').css('border-color', 'red');
}
else {
$('#poster_text').css('border-color', '');
}
};
function logwithoutform() {
if ($('#poster_text').val() == '') {
$('#poster_text').css('border-color', 'red');
}
else {
$('#poster_text').css('border-color', '');
}
};
And heres the controller code but that shouldn't be too important:
[HttpPost]
public ActionResult AccountCreated(Models.AccountViewModel model)
{
String Account_Name = model.Account_Name;
String Account_Password = model.Password;
if (!ModelState.IsValid)
{
return RedirectToAction("CreateAccount");
}
//if (Account_Name == null || Account_Password == null)
// return RedirectToAction("CreateAccount");
WebForumEntities2 db = new WebForumEntities2();
foreach(Account eachAccount in db.Accounts)
{
if (eachAccount.Account_Name.Equals(Account_Name))
{
return RedirectToAction("AccountCreatedMessage");
}
}
int nextiD = 0;
if (db.Accounts.ToList().Count > 0)
{
nextiD = db.Accounts.ToList().Last().Id + 1;
}
var newAccount = new Account();
newAccount.Account_Name = Account_Name;
newAccount.Password = Account_Password;
newAccount.Id = nextiD;
db.Accounts.Add(newAccount);
db.SaveChanges();
return RedirectToAction("CreateAccount");
}
Please help me make the textboxes turn red.
I've tried debugging, and the javascript functions are never called.
First I would use data attributes for field validation.
public class AccountViewModel
{
[Required] // data attribute
public string Account_Name;
[Required]
public string Password;
}
You can then submit your form normally. If the ASP.NET engine picks up any data validation errors it will put the class .field-validation-error on your inputs.
You can style this class to your liking, like so:
.field-validation-error
{
border-color: red;
}
A few other notes:
You have a form nested in another form, I would remove the form
around your button.
Not sure why you put your inputs into a string
in your controller instead of using your ViewModel.
I typically put my DbContext outside of my ActionResults, be sure to dispose of it.
I have an amount field in a view that is required if a checkbox is checked.
Once Razor renders the View with Model data, and a user checks a checkbox without a corresponding amount entered. The Validation message appears. If I de-select that checkbox, the validation message does not disappear.
I've tried to use jquery to remove all the rules generated, but if the user were to checkbox again, prior to post back, those validation rules would have been removed (unless I store them... which is getting really ugly.)
Is there an acceptable way to re-validate client-side with the same requirements in the MVC Model?
Model:
[Display(Name = "Include Amount")]
public bool IncludeAmount { get; set; }
[Display(Name = "Amount")]
[RequiredIf("IncludeAmount", TargetValue = true, ErrorMessage = "Amount is required.")]
[MaxDigits(10, 2)]
[RegularExpression(RegularExpressions.Money, ErrorMessage = ErrorMessages.NumericValueInvalidFormat)]
[GreaterThanZero]
public Nullable<decimal> Amount { get; set; }
View:
<td class="dataEntryLabel" colspan="2">
#Html.LabelFor(model => model.IncludeAmount)
</td>
<td class="dataEntryField" colspan="2">
#Html.CheckBoxFor(model => model.IncludeAmount, new { id = "IncludeAmount" })
<span class="dollar-sign">#Html.TextBoxFor(model => model.Amount, "{0:F}", new { id = "Amount", disabled = "disabled" })</span>
#Html.ValidationMessageFor(model => model.Amount)
</td>
JavaScript (Client-side):
function fixUnobtrusiveValidations() {
var form = getForm();
(<any>$).validator.unobtrusive.parse(form);
}
function onClickCheckBoxIncludeAmount(){
fixUnobtrusiveValidations();
}
$('IncludeAmount').click(onClickCheckBoxIncludeAmount);
Try this to disable the client side validation on onclick events
Refer: https://jqueryvalidation.org/validate/#onclick
$("#myform").validate({
onclick: false,
});
OR
$("#yourChkboxID").validate({
onclick: false,
});
This worked:
if (!($('#IncludeAmount').checked)){
toggleValidatorVisibility($('#Amount'), false);
}
function toggleValidatorVisibility(element: any, value) {
var td: any = element.closest('td');
if (value) {
td.find('span.field-validation-error').show();
} else {
td.find('span.field-validation-error').empty();
}
}
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 =)
Controller
[Authorize]
public ActionResult Create()
{
var LeaveType = new SelectList(new[]
{
new { ID = "0", Name = "" },
new { ID = "1", Name = "Full day leave" },
new { ID = "2", Name = "Half day AM leave" },
new { ID = "3", Name = "Half day PM leave" },
new { ID = "4", Name = "Time off" },
},
"ID", "Name", 0);
ViewData["LeaveType"] = LeaveType;
return View();
}
View
<div class="form-group">
<div class="col-md-4 col-md-offset-4">
<label class="text-center">Leave Type</label>
#Html.DropDownList("LeaveType", null, htmlAttributes: new { #class = "form-control" })
</div>
</div>
Script
$('#LeaveType').change(function () {
var value = $(this).val();
if (value == "0") {
$('#EndDate').closest('.form-group').hide();
$('#StartDate').closest('.form-group').hide();
$('#datetimepicker6').closest('.form-group').hide();
$('#datetimepicker7').closest('.form-group').hide();
$('#leaveReason').closest('.form-group').hide();
$('#createBtn').closest('.form-group').hide();
$('#cancelBtn').closest('.form-group').hide();
}
else if (value == "1") {
$('#EndDate').closest('.form-group').show();
$('#StartDate').closest('.form-group').show();
$('#datetimepicker6').closest('.form-group').hide();
$('#datetimepicker7').closest('.form-group').hide();
$('#leaveReason').closest('.form-group').show();
$('#createBtn').closest('.form-group').show();
$('#cancelBtn').closest('.form-group').show();
#*#Html.ValueFor(CurrentApplication.)*#
}
else if (value == "2") {
$('#EndDate').closest('.form-group').hide();
$('#StartDate').closest('.form-group').show();
$('#datetimepicker6').closest('.form-group').hide();
$('#datetimepicker7').closest('.form-group').hide();
$('#leaveReason').closest('.form-group').show();
$('#createBtn').closest('.form-group').show();
$('#cancelBtn').closest('.form-group').show();
}
else if (value == "3") {
$('#EndDate').closest('.form-group').hide();
$('#startDate').closest('.form-group').show();
$('#datetimepicker6').closest('.form-group').hide();
$('#datetimepicker7').closest('.form-group').hide();
$('#leaveReason').closest('.form-group').show();
$('#createBtn').closest('.form-group').show();
$('#cancelBtn').closest('.form-group').show();
}
else {
$('#EndDate').closest('.form-group').hide();
$('#StartDate').closest('.form-group').hide();
$('#datetimepicker6').closest('.form-group').show();
$('#datetimepicker7').closest('.form-group').show();
$('#leaveReason').closest('.form-group').show();
$('#createBtn').closest('.form-group').show();
$('#cancelBtn').closest('.form-group').show();
}
});
My LeaveType is a drop down list where users can select what kind of leave they want to apply for (eg. Full day/half day/time off). When they select the value on the drop down list, i want to hide or show certain elements because some may not be required based on the type of leave.
I have a startDate and endDate textbox and for half day, i won't show the endDate textbox but i want to set the endDate to be the same as startDate if the user selects the halfday selection from the dropdownlist. I'm guessing I should have a if else loop and I know how to write the codes but I have no idea where to put it.
Also, when i display the data in a table, my drop down list values are display as the ID. How do I display the Name of the LeaveType instead? All help appreciated ^^ Thanks!
You can do it using the change event of #StartDate like following. Hope this will help you.
$('#StartDate').change(function() {
var endDate = $('#EndDate');
if ($('#LeaveType').val()==2) {
endDate.val($(this).val());
}
});
I am using kendoui widgets with knockoutjs for datasource. I have a checkbox that is data bound to StartClientFromWebEnabled observable variable. An input text box is visible only when the checkbox ic checked (StartClientFromWebEnabled is true). The input has a required attribute. I want the required validation to be triggered only when the checkbox is checked.
Here is my html:
<table>
<tr>
<td><label for="startClientFromWebEnabled">Client Launch From Web:</label></td>
<td><input type="checkbox" id="startClientFromWebEnabled" name="startClientFromWebEnabled" data-bind="checked: StartClientFromWebEnabled, enable: IsEditable" onchange="startClientFromWebToggleRequiredAttribute()" /></td>
</tr>
<tr data-bind="visible: StartClientFromWebEnabled">
<td><label for="mimeType">Protocol:</label></td>
<td>
<input id="mimeType" name="mimeType" data-bind= "value: MimeType, enable: IsEditable" />
<span class="k-invalid-msg" data-for="mimeType"></span>
</td>
</tr>
</table>
I tried some scenarios including setting onChange event on the checkbox with the following javascript function adding and removing the required attribute:
startClientFromWebToggleRequiredAttribute = function () {
var checkbox = document.getElementById("startClientFromWebEnabled");
var mimeType = document.getElementById("mimeType");
if (checkbox.checked) {
mimeType.setAttribute("required", "required");
}
else {
mimeType.removeAttribute("required");
}
}
The problem is I will need this functionality for many dependent properties in my application and my option is to make this function generic with some parameters and call it from the html with the corresponding paramater values like this:
toggleRequiredAttribute = function (checkboxElement, inputElement1, inputElement2 ... ) {
var checkbox = document.getElementById(checkboxElement);
var inputElement1 = document.getElementById(inputElement1);
if (checkbox.checked) {
inputElement1.setAttribute("required", "required");
}
else {
inputElement1.removeAttribute("required");
}
}
<input type="checkbox" id="startClientFromWebEnabled" name="startClientFromWebEnabled" data-bind="checked: StartClientFromWebEnabled, enable: IsEditable" onchange="toggleRequiredAttribute('startClientFromWebEnable', 'mimeType')" />
I really do not like this scenario. I wonder is there something like a conditional validation in kendoui that trigger only when some condition is satisfied. Any other suggestions are also welcome.
I had the same issue, I created a custom validator which also handles the server side validation, this example is not 100% complete but all the validation is working, this validates the string length dependant on a checkbox state, it also uses resources for error message etc so will need a little modification, it uses the kendo ui validation client side, let me know if this is useful:
Model Properties:
public bool ValidateTextField { get; set; }
[CustomValidator("ValidateTextField", 6, ErrorMessageResourceType=typeof(Errors),ErrorMessageResourceName="STRINGLENGTH_ERROR")]
public string TextField{ get; set; }
Custom Validator:
[AttributeUsage(AttributeTargets.Field|AttributeTargets.Property, AllowMultiple=false, Inherited=true)]
public class CustomValidatorAttribute : ValidationAttribute, IClientValidatable {
private const string defaultErrorMessage="Error here.";
private string otherProperty;
private int min;
public CustomValidatorAttribute(string otherProperty, int min) : base(defaultErrorMessage) {
if(string.IsNullOrEmpty(otherProperty)) {
throw new ArgumentNullException("otherProperty");
}
this.otherProperty=otherProperty;
this.min=min;
this.ErrorMessage = MyResources.Errors.STRINGLENGTH_ERROR;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext) {
bool valid = true;
var curProperty = validationContext.ObjectInstance.GetType().
GetProperty(otherProperty);
var curPropertyValue = curProperty.GetValue
(validationContext.ObjectInstance, null);
if(Convert.ToBoolean(curPropertyValue)) {
string str=value.ToString();
valid = str.Length >= min;
if(!valid) { return new ValidationResult(MyResources.Errors.STRINGLENGTH_ERROR); }
}
return ValidationResult.Success;
}
#region IClientValidatable Members
public System.Collections.Generic.IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) {
var rule=new ModelClientValidationRule {
ErrorMessage = this.ErrorMessage,
ValidationType="checkboxdependantvalidator"
};
rule.ValidationParameters["checkboxid"]=otherProperty;
rule.ValidationParameters["min"]=min;
yield return rule;
}
public override string FormatErrorMessage(string name) {
return String.Format(CultureInfo.CurrentUICulture, ErrorMessageString,
name);
}
}
Javascript:
(function ($, kendo) {
$.extend(true, kendo.ui.validator, {
rules: { // custom rules
customtextvalidator: function (input, params) {
//check for the rule attribute
if (input.filter("[data-val-checkboxdependantvalidator]").length) {
//get serialized params
var checkBox = "#" + input.data("val-checkboxdependantvalidator-checkboxid");
var min = input.data("val-checkboxdependantvalidator-min");
var val = input.val();
if ($(checkBox).is(':checked')) {
if (val.length < min) {
return false;
}
}
}
return true;
}
},
messages: { //custom rules messages
customtextvalidator: function (input) {
// return the message text
return input.attr("data-val-checkboxdependantvalidator");
}
}
});
})(jQuery, kendo);
Helpful posts:
http://www.codeproject.com/Articles/301022/Creating-Custom-Validation-Attribute-in-MVC-3
http://blogs.msdn.com/b/simonince/archive/2011/02/04/conditional-validation-in-asp-net-mvc-3.aspx