Używam doskonałej wtyczki jQuery Validate do sprawdzania poprawności niektórych formularzy. Na jednym formularzu muszę się upewnić, że użytkownik wypełni przynajmniej jedno z grup pól. Myślę, że mam całkiem dobre rozwiązanie i chciałem się nim podzielić. Zaproponuj wszelkie ulepszenia, o których możesz pomyśleć.
Nie znajdując wbudowanego sposobu, aby to zrobić, przeszukałem i znalazłem niestandardową metodę walidacji Rebecci Murphey , która była bardzo pomocna.
Poprawiłem to na trzy sposoby:
- Aby umożliwić Ci przekazanie selektora dla grupy pól
- Aby umożliwić określenie, ile z tej grupy musi zostać wypełnionych, aby walidacja przebiegła pomyślnie
- Pokazanie wszystkich wejść w grupie jako pozytywnych, gdy tylko jeden z nich przejdzie walidację. (Zobacz odpowiedź dla Nicka Cravera na końcu).
Możesz więc powiedzieć „co najmniej X wejść pasujących do selektora Y musi być wypełnionych”.
Wynik końcowy, z takimi znacznikami:
<input class="productinfo" name="partnumber">
<input class="productinfo" name="description">
... to taka grupa reguł:
// Both these inputs input will validate if
// at least 1 input with class 'productinfo' is filled
partnumber: {
require_from_group: [1,".productinfo"]
}
description: {
require_from_group: [1,".productinfo"]
}
Punkt 3 zakłada, że dodajesz klasę .checked
do komunikatów o błędach po pomyślnej weryfikacji. Możesz to zrobić w następujący sposób, jak pokazano tutaj .
success: function(label) {
label.html(" ").addClass("checked");
}
Podobnie jak w powyższej demonstracji, używam CSS, aby nadać każdemu span.error
obraz X jako tło, chyba że ma klasę .checked
, w którym to przypadku otrzymuje obraz znacznika wyboru.
Oto mój dotychczasowy kod:
jQuery.validator.addMethod("require_from_group", function(value, element, options) {
var numberRequired = options[0];
var selector = options[1];
//Look for our selector within the parent form
var validOrNot = $(selector, element.form).filter(function() {
// Each field is kept if it has a value
return $(this).val();
// Set to true if there are enough, else to false
}).length >= numberRequired;
// The elegent part - this element needs to check the others that match the
// selector, but we don't want to set off a feedback loop where each element
// has to check each other element. It would be like:
// Element 1: "I might be valid if you're valid. Are you?"
// Element 2: "Let's see. I might be valid if YOU'RE valid. Are you?"
// Element 1: "Let's see. I might be valid if YOU'RE valid. Are you?"
// ...etc, until we get a "too much recursion" error.
//
// So instead we
// 1) Flag all matching elements as 'currently being validated'
// using jQuery's .data()
// 2) Re-run validation on each of them. Since the others are now
// flagged as being in the process, they will skip this section,
// and therefore won't turn around and validate everything else
// 3) Once that's done, we remove the 'currently being validated' flag
// from all the elements
if(!$(element).data('being_validated')) {
var fields = $(selector, element.form);
fields.data('being_validated', true);
// .valid() means "validate using all applicable rules" (which
// includes this one)
fields.valid();
fields.data('being_validated', false);
}
return validOrNot;
// {0} below is the 0th item in the options field
}, jQuery.format("Please fill out at least {0} of these fields."));
Brawo!
Wykrzyczeć
Teraz do tego okrzyku - pierwotnie mój kod po prostu ślepo ukrywał komunikaty o błędach w innych pasujących polach zamiast ich ponownego sprawdzania, co oznaczało, że jeśli był inny problem (na przykład `` dozwolone są tylko cyfry i wpisałeś litery '') , został ukryty, dopóki użytkownik nie próbował go przesłać. Stało się tak, ponieważ nie wiedziałem, jak uniknąć pętli opinii, o której mowa w komentarzach powyżej. Wiedziałem, że musi istnieć sposób, więc zadałem pytanie , a Nick Craver oświecił mnie. Dzięki, Nick!
Pytanie rozwiązane
Pierwotnie było to pytanie typu „pozwól mi się tym podzielić i zobaczę, czy ktoś może zasugerować ulepszenia”. Chociaż nadal chciałbym otrzymywać opinie, myślę, że w tym momencie jest całkiem kompletny. (Może być krótszy, ale chcę, aby był łatwy do odczytania i niekoniecznie zwięzły). Po prostu baw się!
Aktualizacja - teraz część walidacji jQuery
Zostało to oficjalnie dodane do walidacji jQuery w dniu 03.04.2012.
źródło
Odpowiedzi:
To doskonałe rozwiązanie, Nathan. Wielkie dzięki.
Oto sposób, aby powyższy kod działał na wypadek, gdyby ktoś miał problemy z integracją, tak jak ja:
Kod wewnątrz pliku additional-methods.js :
Kod w pliku html :
Nie zapomnij dołączyć pliku dodatkowego-methods.js!
źródło
require_from_group: [1,".partnumber"]
i...[1,".contactname"]
upewnić się, że sprawdzasz właściwe rzeczy.Niezłe rozwiązanie. Jednak miałem problem z niedziałającymi innymi wymaganymi regułami. Wykonanie .valid () w formularzu rozwiązało ten problem.
źródło
validator.formSubmit = true
. Następnie w metodzie require-from-group sprawdzam tę flagę; jeśli to tam robię$(element.form).valid();
, w przeciwnym razie robięfields.valid();
.Dzięki, sean. To rozwiązało problem, który miałem z kodem ignorującym inne reguły.
Wprowadziłem też kilka zmian, aby komunikat „Proszę wypełnić co najmniej 1 pole…” był wyświetlany w osobnym div zamiast po każdym polu.
umieścić w formie skryptu walidacyjnego
dodaj to gdzieś na stronie
dodaj do funkcji addMethod metody require_from_group
źródło
Przesłałem łatkę , która nie cierpi z powodu problemów występujących w obecnej wersji (gdy opcja „wymagana” przestaje działać poprawnie na innych polach, dyskusja o problemach z aktualną wersją jest na githubie .
Przykład na http://jsfiddle.net/f887W/10/
źródło
Rozpoczynanie nazwy zmiennej od $ jest wymagane w PHP, ale dość dziwne (IMHO) w JavaScript. Sądzę też, że nazywasz to dwukrotnie „$ module” i raz „module”, prawda? Wygląda na to, że ten kod nie powinien działać.
Nie jestem również pewien, czy to normalna składnia wtyczki jQuery, ale mogę dodać komentarze nad wywołaniem addMethod, wyjaśniając, co osiągasz. Nawet przy powyższym opisie tekstowym trudno jest śledzić kod, ponieważ nie wiem, do jakiego zestawu pól: wypełnione, wartość, element lub selektor się odnoszą. Być może większość z tego jest oczywista dla kogoś zaznajomionego z wtyczką Validate, więc kieruj się oceną, jaka jest odpowiednia ilość wyjaśnień.
Być może mógłbyś wydzielić kilka zmiennych, aby samodzielnie udokumentować kod; lubić,
(zakładając, że rozumiem znaczenie tych fragmentów twojego kodu! :))
Nie jestem do końca pewien, co właściwie oznacza „moduł” - czy jest jakaś bardziej szczegółowa nazwa, którą mógłbyś nadać tej zmiennej?
Ogólnie niezły kod!
źródło
Ponieważ formularz, nad którym pracuję, ma kilka sklonowanych regionów z takimi pogrupowanymi danymi wejściowymi, przekazałem dodatkowy argument do konstruktora require_from_group, zmieniając dokładnie jedną linię funkcji addMethod:
iw ten sposób selektor, identyfikator lub nazwę elementu można przekazać raz:
a walidator ograniczy walidację do elementów z tą klasą tylko w każdym zestawie pól, zamiast próbować policzyć wszystkie sklasyfikowane elementy .reqgrp w formularzu.
źródło
Oto moje pęknięcie w odpowiedzi Rocket Hazmat, próbując rozwiązać problem innych zdefiniowanych pól, które również wymagają walidacji, ale oznaczając wszystkie pola jako prawidłowe po pomyślnym wypełnieniu jednego.
Jedynym pozostałym problemem z tym teraz jest przypadek skrajny, w którym pole jest puste, następnie wypełnione, a następnie ponownie puste ... w takim przypadku błąd zostanie zastosowany do pojedynczego pola, a nie do grupy. Ale wydaje się to tak mało prawdopodobne z jakąkolwiek częstotliwością i nadal działa technicznie w tym przypadku.
źródło
Miałem problemy z innymi regułami, które nie były sprawdzane w związku z tym, więc zmieniłem:
Do tego:
Wprowadziłem też kilka (osobistych) ulepszeń i to jest wersja, której używam:
źródło
Dzięki, Nathan. Zaoszczędziłeś mi mnóstwo czasu.
Muszę jednak zauważyć, że ta reguła nie jest gotowa na jQuery.noConflict (). Tak więc, aby pracować z, powiedzmy, trzeba zamienić wszystkie $ na jQuery
var $j = jQuery.noConflict()
I mam pytanie: jak sprawić, by zachowywał się jak wbudowana reguła? Na przykład, jeśli wpiszę adres e-mail, komunikat „Wprowadź prawidłowy adres e-mail” znika automatycznie, ale jeśli wypełnię jedno z pól grupy, komunikat o błędzie pozostaje.
źródło