2010-03-24 5 views
8

Mam dwie grupy sprawdzania poprawności: rodzic i dzieckoJak sprawdzać zgodność z wieloma grupami sprawdzania poprawności?

Mam przycisk dodawania, który musi jedynie zatwierdzić grupę sprawdzania podrzędnego, która jest łatwa do wykonania. Przycisk zapisu musi zostać zweryfikowany względem grup sprawdzania rodzicielskiego i podrzędnego, zarówno po stronie klienta, jak i po stronie serwera. Myślę, że wiem, jak to zrobić po stronie serwera, wywołując metodę Page.Validate ("groupname") dla każdej grupy, ale jak to zrobić po stronie klienta?

Odpowiedz

13

powinien być w stanie to osiągnąć poprzez tworzenie funkcji javascript, który używa Page_ClientValidate a następnie konieczności połączenia przycisk tej funkcji

<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> 
+1

Myślę, że trzeba zmienić OnClientClick do "powrotu validate()" –

1

Jeśli zadzwonisz Page_ClientValidate (..) dwa razy, tylko ostatni wynik będzie walidacja być pokazane i może być OK, podczas gdy pierwsze nie. Więc drugie połączenie powinno być wykonane tylko wtedy, gdy pierwsze powrócił prawdziwy

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

    return parentOk && childOk; 
</script> 
1

Cokolwiek sposób można zrobić to wymaga pewnej hacking ominąć ASP.NET założeniu, że nie będzie starać się to zrobić. Opowiadam się za podejściem wielokrotnego użytku, które jest jednoznaczne w odniesieniu do hakerów.

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>"; 
    } 
} 
4

Problem z odpowiedzią CAbbott jest to, że błędy walidacji, które występują w grupie „macierzystej” nie będą wyświetlane po wywołaniu zatwierdzania grupę „dziecko”. Najmniejszym problemem z odpowiedzią Olega jest to, że walidacja grupy "dziecko" nie nastąpi, dopóki grupa "nadrzędna" nie będzie gotowa.

Wszystko, co naprawdę musimy zrobić, aby umożliwić walidację po stronie klienta więcej niż jednej grupy w tym samym czasie, to przesłonięcie metody Javascript IsValidationGroupMatch, która określa, czy kontrola ma zostać włączona do bieżącego zestawu, który jest sprawdzany.

Na przykład:

(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');" />