MVC3 Client-side validation when collecting at least one item with a value

My viewmodel

Public Class ViewModel <SelectOne()> Public Property Collection As List(Of Item) End Class 

My model

 Public Class Item <SelectOneProperty(TargetValue:=True, ErrorMessage:="Select at least one.")> Public Property Selected As Boolean Public Property Value As String End Class 

In my opinion, I am drawing ViewModel.Collection with an editor template

 @Html.CheckBoxFor(Function(item) item.Selected) @Html.HiddenFor(Function(item) item.Value) 

Now, what I want is to make sure that at least one checkbox is selected using client-side validation.

I can achieve this by setting my own validation attribute in the Item.Selected property and registering a new adapter through $.validator.unobtrusive.adapters.add()

But I believe that the attribute should be more likely in ViewModel.Collection , as on the server side. I already check if one of the elements in the collection has Selected = True using this selective check:

 <AttributeUsage(AttributeTargets.Field Or AttributeTargets.Property, AllowMultiple:=False, Inherited:=False)> Public Class SelectOneAttribute Inherits ValidationAttribute Protected Overrides Function IsValid(value As Object, validationContext As ValidationContext) As ValidationResult Dim list As IList If value Is Nothing Then Return Nothing End If If TypeOf value Is IEnumerable Then list = CType(value, IList) Else list = New Object() {value} End If Dim count As Integer = (From item In list From prop In item.GetType().GetProperties() Let attributes = prop.GetCustomAttributes(GetType(RequireOneOrMoreIndicatorAttribute), False) Where attributes.Count > 0 From attribute In attributes Where attribute.TargetValue = prop.GetValue(item, Nothing)).Count() If count > 0 Then Return Nothing End If Return New ValidationResult(FormatErrorMessage(validationContext.DisplayName)) End Function End Class 

It uses reflection on SelectOnePropertyAttribute to find which property is being checked:

 <AttributeUsage(AttributeTargets.Field Or AttributeTargets.Property, AllowMultiple:=False, Inherited:=False)> Public Class SelectOnePropertyAttribute Inherits ValidationAttribute Implements IClientValidatable Public Property TargetValue As Object Public Sub New(targetValue As Object) Me.TargetValue = targetValue End Sub Public Overrides Function IsValid(value As Object) As Boolean Return True End Function Public Function GetClientValidationRules(metadata As System.Web.Mvc.ModelMetadata, context As System.Web.Mvc.ControllerContext) _ As System.Collections.Generic.IEnumerable(Of System.Web.Mvc.ModelClientValidationRule) _ Implements System.Web.Mvc.IClientValidatable.GetClientValidationRules Dim rule As New ModelClientValidationRule With { .ValidationType = "selectone", .ErrorMessage = Me.ErrorMessage } Return New ModelClientValidationRule() {rule} End Function End Class 

And this is a client-side check

 $.validator.unobtrusive.adapters.add("selectone", function (options) { options.rules["selectone"] = {}; options.messages["selectone"] = options.message; }); $.validator.addMethod("selectone", function (value, element, parameters) { var $el = $(element), name = $el.attr("name"), field = name.replace(/\[.*$/, "").replace(".", "_"), attr = name.replace(/^.*\./, ""), test = new RegExp(field + "\\[\\d\\]\." + attr); var inputs = $("input[id^=" + field + "]:not([disabled]):not([type=hidden])").filter("input[name$=" + attr + "]"); for(var i = 0; i < this.errorList.length; i++) { var name = $(this.errorList[i].element).attr("name"); // Do not write out the error more than once. if (test.test(name)) return true; } return inputs.length == 0 || inputs.filter(":checked:not([disabled])").val(); }); 
+4
source share
3 answers

You create a custom validation that will work on the side, but if you want to run on the client side, then you need to create jQuery for this custom validation, and then it to your page.

Please refer to the links below.

http://www.codeproject.com/Articles/275056/Custom-Client-Side-Validation-in-ASP-NET-MVC3

http://www.falconwebtech.com/post/2012/04/21/MVC3-Custom-Client-Side-Validation-with-Unobtrusive-Ajax.aspx

0
source

Make the following change: -

1.In view ViewModel: -

 Public Class ViewModel <SelectOne()> <SelectOneProperty(TargetValue:=True, ErrorMessage:="Select at least one.")> Public Property Collection As List(Of Item) End Class 
  • My model: -

    Public class Public property selected as logical Public property value as string End class

  • In your view, add the following line:

    @ Html.HiddenFor (x => x.ItemCollection)

4. Then you run the view and see the view source, then it will be

4. Then you send the code, then it will perform a client-side check. add debugger and debug it

5. Then change the client side of the script. 1. Now you can extract a value from each checkbox and verify that any of your checkboxes is selected, and then submit the form, otherwise display the result.

6. Also make a change to SelectOnePropertyAttribute as per your requirement

7. And for the server side I made this code in C #: -

[AttributeUsage ((AttributeTargets.Field | AttributeTargets.Property), AllowMultiple = false, Inherited = false)] public class SelectOneAttribute: ValidationAttribute {public String PropertyName {get; set; }

  protected override ValidationResult IsValid(object value, ValidationContext validationContext) { bool boolVal = false; IList list; if (value == null) { return null; } if (value.GetType().Name == typeof(List<>).Name || value.GetType().Name == typeof(IList<>).Name) { list = (IList)value; } else { list = new object[] {value}; } if (list.Count<0) return null; if ((from object item in list let propertyInfo = item.GetType().GetProperties() from info in propertyInfo where String.Equals(info.Name, PropertyName) && (bool)info.GetValue(item) == true select item).Any()) { return null; } return new ValidationResult(FormatErrorMessage(validationContext.DisplayName)); } } 
0
source

That's what you need? This will prevent the form from being submitted unless "myCheckbox" is checked ...

 $(document).ready(function () { $('#submitButtonId').click(function (e) { if ($('input[name=myCheckbox]:checked').length == 0) { e.preventDefault(); alert('Please choose at least one checkbox before continuing!'); } }); }); 
0
source

Source: https://habr.com/ru/post/1433802/


All Articles