Как выполнить проверку по нескольким группам проверки?

У меня две группы проверки: родительская и дочерняя

У меня есть кнопка добавления, которая должна проверять только дочернюю группу проверки, что легко сделать. Кнопка сохранения должна проверяться на соответствие родительской и дочерней группам проверки как на стороне клиента, так и на стороне сервера. Думаю, я знаю, как это сделать на стороне сервера, вызывая метод Page.Validate ("groupname") для каждой группы, но как это сделать на стороне клиента?


person Jeremy    schedule 24.03.2010    source источник


Ответы (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>
person CAbbott    schedule 24.03.2010
comment
Я думаю, вам нужно изменить OnClientClick, чтобы вернуть validate () - person Mr Bell; 28.01.2011

Проблема с ответом 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');" />
person Remi Despres-Smyth    schedule 28.08.2013

Если вы вызовете Page_ClientValidate (..) дважды, будет показан только последний результат проверки, и он может быть нормальным, а первый - нет. Таким образом, второй вызов должен выполняться только в том случае, если первый вернул истину.

<script type="text/javascript">
    var parentOk= Page_ClientValidate('parent');
    var childOk = false;
    if (parentOk) {
        childOk = Page_ClientValidate('child');
    }

    return parentOk && childOk;
</script>
person Oleg    schedule 26.10.2012

Каким бы способом вы это ни делали, требуется некоторый взлом, чтобы обойти предположение 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 &lt; Page_Validators.length; i++) {
        Page_Validators[i].finalValid = true;
    }
    if (Page_ValidationSummaries) {
        for (i = 0; i &lt; Page_ValidationSummaries.length; i++) {
            Page_ValidationSummaries[i].finalDisplay = ""none"";
        }
    }

    // Validate.
    var groupValid = PageMod_DoValidation(validationGroup);

    // Update displays once.
    for (i = 0; i &lt; Page_Validators.length; i++) {
        ctrl = Page_Validators[i];
        ctrl.isvalid = ctrl.finalValid;
        ValidatorUpdateDisplay(ctrl);
    }
    if (Page_ValidationSummaries) {
        for (i = 0; i &lt; 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 &lt; Page_Validators.length; i++) {
        validator = Page_Validators[i];
        ValidatorValidate(validator, validationGroup, null);
        validator.finalValid &amp;= validator.isvalid;
        groupValid &amp;= validator.isvalid;
    }

    if (Page_ValidationSummaries) {
        ValidationSummaryOnSubmit(validationGroup, groupValid);

        var summary;
        for (i = 0; i &lt; Page_ValidationSummaries.length; i++) {
            summary = Page_ValidationSummaries[i];
            if (summary.style.display !== ""none"") summary.finalDisplay = summary.style.display;
        }
    }

    return groupValid;
}
</script>";
    }
}
person Peter Taylor    schedule 24.01.2013