Как проверить по нескольким группам проверки?
У меня есть две группы проверки: родитель и ребенок
У меня есть кнопка добавления, которая должна проверять только дочернюю группу проверки, что легко сделать. Кнопка сохранения должна быть проверена на соответствие родительской и дочерней группам проверки как на стороне клиента, так и на стороне сервера. Я думаю, что я знаю, как сделать это на стороне сервера, вызывая метод Page.Validate("groupname") для каждой группы, но как это можно сделать на стороне клиента?
4 ответа
Вы должны быть в состоянии сделать это, создав функцию JavaScript, которая использует Page_ClientValidate, а затем вызывая эту функцию кнопкой.
<asp:Button ID="btnSave" Text="Save" OnClientClick="return validate()" runat="server" />
<script type="text/javascript">
function validate() {
var t1 = Page_ClientValidate("parent");
var t2 = Page_ClientValidate("child");
if (!t1 || !t2) return false;
return true;
}
</script>
Проблема с ответом CAbbott заключается в том, что ошибки проверки, которые происходят в "родительской" группе, не будут отображаться после вызова для проверки "дочерней" группы. Более незначительная проблема с ответом Олега состоит в том, что проверка "дочерней" группы не произойдет, пока "родительская" группа не будет готова.
Все, что нам действительно нужно сделать, чтобы разрешить проверку на стороне клиента более чем одной группы одновременно, - это переопределить метод Javascript IsValidationGroupMatch, который определяет, следует ли включать элемент управления в текущий проверяемый набор.
Например:
(function replaceValidationGroupMatch() {
// If this is true, IsValidationGroupMatch doesn't exist - oddness is afoot!
if (!IsValidationGroupMatch) throw "WHAT? IsValidationGroupmatch not found!";
// Replace ASP.net's IsValidationGroupMatch method with our own...
IsValidationGroupMatch = function(control, validationGroup) {
if (!validationGroup) return true;
var controlGroup = '';
if (typeof(control.validationGroup) === 'string') controlGroup = control.validationGroup;
// Deal with potential multiple space-delimited groups being validated
var validatingGroups = validationGroup.split(' ');
for (var i = 0; i < validatingGroups.length; i++) {
if (validatingGroups[i] === controlGroup) return true;
}
// Control's group not in any being validated, return false
return false;
};
} ());
// You can now validate against multiple groups at once, for example:
// space-delimited list. This would validate against the Decline group:
//
// Page_ClientValidate('Decline');
//
// while this would validate against the Decline, Open and Complete groups:
//
// Page_ClientValidate('Open Decline Complete');
//
// so if you wanted to validate all three upon click of a button, you'd do:
<asp:Button ID="yourButton" runat="server"
OnClick="ButtonSave_Click" CausesValidation="false"
OnClientClick="return Page_ClientValidate('Open Decline Complete');" />
Независимо от того, что вы делаете, это требует некоторого взлома, чтобы обойти предположение ASP.Net, что вы не будете пытаться сделать это. Я предпочитаю многократно используемый подход, который явно касается хакерства.
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebSandbox.Validators
{
/// <summary>
/// <para>
/// Validates a different validation group. Among the use cases envisioned are
/// <list type="">
/// <item>
/// Validating one set of rules when the user clicks "Save draft" and validating those rules plus some
/// extra consistency checks when they click "Send".
/// </item>
/// <item>
/// Grouping controls in a <code>fieldset</code> into a validation group with a
/// <code>ValidationSummary</code> and then having a final <code>ValidationSummary</code> which tells the
/// user which groups still have errors.
/// </item>
/// </list>
/// </para>
/// <para>
/// We include checks against setting <code>GroupToValidate</code> to the same value as
/// <code>ValidationGroup</code>, but we don't yet include checks for infinite recursion with one validator
/// in group A which validates group B and another in group B which validates group A. Caveat utilitor.
/// </para>
/// </summary>
public class ValidationGroupValidator : BaseValidator
{
public string GroupToValidate
{
get { return ViewState["G2V"] as string; }
set { ViewState["G2V"] = value; }
}
protected override bool ControlPropertiesValid()
{
if (string.IsNullOrEmpty(GroupToValidate)) throw new HttpException("GroupToValidate not specified");
if (GroupToValidate == ValidationGroup) throw new HttpException("Circular dependency");
// Don't call the base, because we don't want a "control to validate"
return true;
}
protected override void AddAttributesToRender(HtmlTextWriter writer)
{
base.AddAttributesToRender(writer);
writer.AddAttribute("evaluationfunction", "ValidateValidationGroup");
writer.AddAttribute("GroupToValidate", GroupToValidate);
}
protected override void OnPreRender(EventArgs e)
{
// The standard validation JavaScript is too restrictive for this validator to work, so we have to replace a key function.
// Fortunately this runs later than the standard JS, so we can simply overwrite the existing value of Page_ClientValidate.
Page.ClientScript.RegisterStartupScript(typeof(ValidationGroupValidator), "validationJS", _ValidationJS);
base.OnPreRender(e);
}
protected override bool EvaluateIsValid()
{
if (string.IsNullOrEmpty(GroupToValidate)) return false;
bool groupValid = true;
foreach (IValidator validator in Page.GetValidators(GroupToValidate))
{
validator.Validate();
groupValid &= validator.IsValid;
}
return groupValid;
}
private const string _ValidationJS = @"<script type=""text/javascript"">
function ValidateValidationGroup(val) {
if (typeof(val.GroupToValidate) == ""string"") {
val.valid = PageMod_DoValidation(val.GroupToValidate);
}
}
function Page_ClientValidate(validationGroup) {
Page_InvalidControlToBeFocused = null;
if (!Page_Validators) return true;
var i, ctrl;
// Mark everything as valid.
for (i = 0; i < Page_Validators.length; i++) {
Page_Validators[i].finalValid = true;
}
if (Page_ValidationSummaries) {
for (i = 0; i < Page_ValidationSummaries.length; i++) {
Page_ValidationSummaries[i].finalDisplay = ""none"";
}
}
// Validate.
var groupValid = PageMod_DoValidation(validationGroup);
// Update displays once.
for (i = 0; i < Page_Validators.length; i++) {
ctrl = Page_Validators[i];
ctrl.isvalid = ctrl.finalValid;
ValidatorUpdateDisplay(ctrl);
}
if (Page_ValidationSummaries) {
for (i = 0; i < Page_ValidationSummaries.length; i++) {
ctrl = Page_ValidationSummaries[i];
ctrl.style.display = ctrl.finalDisplay;
}
}
ValidatorUpdateIsValid();
Page_BlockSubmit = !Page_IsValid;
return Page_IsValid;
}
function PageMod_DoValidation(validationGroup) {
var groupValid = true, validator, i;
for (i = 0; i < Page_Validators.length; i++) {
validator = Page_Validators[i];
ValidatorValidate(validator, validationGroup, null);
validator.finalValid &= validator.isvalid;
groupValid &= validator.isvalid;
}
if (Page_ValidationSummaries) {
ValidationSummaryOnSubmit(validationGroup, groupValid);
var summary;
for (i = 0; i < Page_ValidationSummaries.length; i++) {
summary = Page_ValidationSummaries[i];
if (summary.style.display !== ""none"") summary.finalDisplay = summary.style.display;
}
}
return groupValid;
}
</script>";
}
}
Если дважды вызвать Page_ClientValidate(..), будет показан только последний результат проверки, и он может быть в порядке, а первый - нет. Таким образом, второй вызов должен быть выполнен, только если первый вернул true
<script type="text/javascript">
var parentOk= Page_ClientValidate('parent');
var childOk = false;
if (parentOk) {
childOk = Page_ClientValidate('child');
}
return parentOk && childOk;
</script>