Come utilizzare i popover di Twitter Bootstrap per le notifiche di convalida jQuery?


84

Posso far apparire i popover usando bootstrap abbastanza facilmente, e posso anche fare validazioni usando il plugin di convalida jQuery standard o il motore di convalida jQuery , ma non riesco a capire come inserire l'uno nell'altro.

Penso che ciò di cui ho bisogno sia un hook che viene chiamato dal validatore quando vuole visualizzare una notifica, dargli una chiusura che passi il messaggio e l'elemento target a un popover. Sembra una sorta di iniezione di dipendenza.

Tutto carino in teoria, ma non riesco a capire dove sia quell'hook, o anche se ne esiste uno in entrambi i motori di convalida. Entrambi sembrano intenzionati ad assumersi la responsabilità di visualizzare le notifiche con tutti i tipi di opzioni elaborate per il posizionamento, i wrapper, gli stili quando tutto ciò che cerco sono i tipi di errore (non ho necessariamente nemmeno bisogno del testo del messaggio) e l'elemento a cui si riferisce per. Ho trovato hook per l'intero modulo, non per le singole notifiche.

Preferisco di gran lunga i sistemi di convalida che utilizzano le classi per definire le regole, poiché giocano bene con i moduli creati dinamicamente.

Qualcuno ha una soluzione o un'idea migliore?

Risposte:


21

Dai un'occhiata alle opzionihighlight e showErrors jQuery Validator , queste ti permetteranno di agganciare le tue evidenziazioni di errore personalizzate che attivano i popover Bootstrap.


È fantastico, grazie. evidenziare e non evidenziare sono ciò che stavo cercando.
Synchro

80

Questo è un esempio pratico:

$('form').validate({
    errorClass:'error',
    validClass:'success',
    errorElement:'span',
    highlight: function (element, errorClass, validClass) { 
        $(element).parents("div[class='clearfix']").addClass(errorClass).removeClass(validClass); 
    }, 
    unhighlight: function (element, errorClass, validClass) { 
        $(element).parents(".error").removeClass(errorClass).addClass(validClass); 
    }
});

inserisci qui la descrizione dell'immagine

Non usa davvero i popover bootstrap, ma sembra davvero carino ed è facile da ottenere.

AGGIORNARE

Quindi, per avere la convalida del popover puoi usare questo codice:

$("form").validate({
  rules : {
    test : {
      minlength: 3 ,
      required: true
    }
  },
  showErrors: function(errorMap, errorList) {
    $.each(this.successList, function(index, value) {
      return $(value).popover("hide");
    });
    return $.each(errorList, function(index, value) {
      var _popover;
      _popover = $(value.element).popover({
        trigger: "manual",
        placement: "top",
        content: value.message,
        template: "<div class=\"popover\"><div class=\"arrow\"></div><div class=\"popover-inner\"><div class=\"popover-content\"><p></p></div></div></div>"
      });
      // Bootstrap 3.x :      
      //_popover.data("bs.popover").options.content = value.message;
      // Bootstrap 2.x :
      _popover.data("popover").options.content = value.message;
      return $(value.element).popover("show");
    });
  }
});

Ottieni qualcosa del genere:

inserisci qui la descrizione dell'immagine

Dai un'occhiata al jsFiddle .


3
Votato perché questo è nella direzione di ciò che stavo cercando. :-) Vedi la mia risposta per una variante.
namin

Cosa fare se si tratta di un modulo multistadio
Tachioni

4
Solo una breve nota che con l'ultima versione di Bootstrap non c'è più una chiave .data ("popover"). Forse per evitare collisioni hanno cambiato la chiave in "bs.popover". Mi ci è voluto un po 'per capire perché stavo ricevendo un errore indefinito . Quindi ora dovrai usare _popover.data ("bs.popover"). Options.content = value.message; nel codice sopra.
davidethell,

Come posso visualizzare il popup su un altro tipo di errore diverso dai campi obbligatori. Voglio dire come posso personalizzarlo per visualizzare l'errore solo su regole specifiche.
arjun

In realtà c'è un piccolo problema che puoi facilmente controllare anche in jsFiddle. Se il campo non è richiesto e qualche regola è infranta, il popover viene visualizzato MA se svuoto il campo e mi concentro su un altro campo, il popover è ancora lì. Il primo ciclo di successList non viene mai chiamato, quindi il popover non è mai in uno stato "nascondi" dopo essere entrato in uno stato "mostra". C'è qualcosa che possiamo fare al riguardo?
G4bri3l

9

Chris Fulstow aveva ragione, ma mi ci è voluto ancora un po ', quindi ecco il codice completo:

Questo mostra il popover in caso di errore e nasconde le etichette di errore predefinite:

$('#login').validate({
  highlight: function(element, errClass) {
    $(element).popover('show');
  },
  unhighlight: function(element, errClass) {
    $(element).popover('hide');
  },
  errorPlacement: function(err, element) {
    err.hide();
  }
}).form();

Questo imposta il popover. L'unica cosa di cui hai bisogno è il trigger: 'manuale'

$('#password').popover({
  placement: 'below',
  offset: 20,
  trigger: 'manual'
});

Gli attributi del titolo e del contenuto passati al popover non funzionavano, quindi li ho specificati in linea nel mio input #password con data-content = "Minimo 5 caratteri" e data-original-title = "Password non valida". Hai anche bisogno di rel = 'popover' nel tuo modulo.

Funziona, ma il popover lampeggia quando si deseleziona. Qualche idea su come risolverlo?


6

Ecco un seguito all'eccellente suggerimento di Varun Singh che evita che il problema dello "sfarfallio" della convalida cerchi costantemente di "mostrare" anche se il popup è già presente. Ho semplicemente aggiunto un array di stati di errore per catturare quali elementi mostrano errori e quali no. Funziona come un fascino!

var errorStates = [];

$('#LoginForm').validate({
    errorClass:'error',
    validClass:'success',
    errorElement:'span',
    highlight: function (element, errorClass) {
        if($.inArray(element, errorStates) == -1){
            errorStates[errorStates.length] = element;
            $(element).popover('show');
        }
    }, 
    unhighlight: function (element, errorClass, validClass) {
        if($.inArray(element, errorStates) != -1){
            this.errorStates = $.grep(errorStates, function(value) {
              return value != errorStates;
            });
            $(element).popover('hide');
        }
    },
    errorPlacement: function(err, element) {
        err.hide();
    }
});

$('#Login_unique_identifier').popover({
    placement: 'right',
    offset: 20,
    trigger: 'manual'
});

$('#Login_password').popover({
    placement: 'right',
    offset: 20,
    trigger: 'manual'
});

Questa è stata l'unica risposta su questa pagina che ha funzionato per me. Peccato che non sia stato più votato.
alastairs

1
Questo non significa che devi definire un esplicito popoverper ogni singolo campo che desideri convalidare? Se è così è da pazzi .
g33kz0r

Per la maggior parte dei casi d'uso, mi aspetto che questo sia perfettamente accettabile. Se hai una soluzione più ottimale, sentiti libero di aggiungerla :)
Jeffrey Gilbert


3

Preferisco cambiare il CSS di bootstrap. Ho appena aggiunto le classi di jQuery validate nel posto giusto. field-validation-error e input-validation-error

    form .clearfix.error > label, form .clearfix.error .help-block, form .clearfix.error .help-inline, .field-validation-error {
  color: #b94a48;
}
form .clearfix.error input, form .clearfix.error textarea, .input-validation-error {
  color: #b94a48;
  border-color: #ee5f5b;
}
form .clearfix.error input:focus, form .clearfix.error textarea:focus, .input-validation-error:focus {
  border-color: #e9322d;
  -webkit-box-shadow: 0 0 6px #f8b9b7;
  -moz-box-shadow: 0 0 6px #f8b9b7;
  box-shadow: 0 0 6px #f8b9b7;
}

Questo approccio sembra migliore per me :). Questo è anche quello che stavo pensando
Freshblood

3

Ecco come l'ho fatto con Bootstrap 2.xe jQuery Validate 1.9

$('#form-register').validate({ errorElement: 'span', errorClass:'help-inline', highlight:    function (element, errorClass) {
        $(element).parent().parent().addClass('error');
    }, unhighlight: function (element, errorClass) {
        $(element).parent().parent().removeClass('error');
    }});

3

Dai un'occhiata a quanto segue:
- https://gist.github.com/3030983
Penso che sia il più semplice di tutti.

MODIFICARE

Codice dal collegamento:

$('form').validate({
    rules: {
        numero: {
            required: true
        },
        descricao: {
            minlength: 3,
            email: true,
            required: true
        }
    },

    showErrors: function (errorMap, errorList) {

        $.each(this.successList, function (index, value) {
            $(value).popover('hide');
        });


        $.each(errorList, function (index, value) {

            console.log(value.message);

            var _popover = $(value.element).popover({
                trigger: 'manual',
                placement: 'top',
                content: value.message,
                template: '<div class="popover"><div class="arrow"></div><div class="popover-inner"><div class="popover-content"><p></p></div></div></div>'
            });

            _popover.data('popover').options.content = value.message;

            $(value.element).popover('show');

        });

    }

});

Molte grazie per l'avviso! Vedi la mia versione per Bootstrap ma con i suggerimenti. Secondo me è più elegante dei popover.
Adrian P.

3

Molte grazie per l'avviso! Ecco la mia versione per Bootstrap ma con i suggerimenti. Secondo me è più elegante dei popover. So che la domanda era per i popover, quindi per favore non votare per questo motivo. Forse a qualcuno piacerà in questo modo. Adoro quando cerco qualcosa e ho trovato nuove idee su Stackoverflow. Nota: non è necessario alcun markup sul modulo.

    $('#LoginForm').validate({
        rules: {
            password: {
                required: true,
                minlength: 6
            },

            email_address: {
                required: true,
                email: true
            }
        },
        messages: {
            password: {
                required: "Password is required",
                minlength: "Minimum length is 6 characters"
            },
            email_address: {
                required: "Email address is required",
                email: "Email address is not valid"
            }
        },  
        submitHandler: function(form) {
            form.submit();
        },

        showErrors: function (errorMap, errorList) {

            $.each(this.successList, function (index, value) {
                $('#'+value.id+'').tooltip('destroy');
            });


            $.each(errorList, function (index, value) {

                $('#'+value.element.id+'').attr('title',value.message).tooltip({
                    placement: 'bottom',
                    trigger: 'manual',
                    delay: { show: 500, hide: 5000 }
                }).tooltip('show');

            });

        }

    }); 

1
Ho provato a usare il tuo approccio, ma stavo iniziando a ottenere un errore. Il problema è che se usi l'interfaccia utente di Jquery otterrai conflitti perché entrambi usano il tooltip. So che esiste una soluzione per questo, ma voglio solo che gli altri utenti lo sappiano.
Richard Pérez

+1 per jQuery UI heads up! Dovrai configurare il tuo download personalizzato (jQueryUI o Bootstrap) per NON includere le funzioni JS Tooltip. Sarà comunque un conflitto per qualsiasi suggerimento se non lo fai.
Adrian P.

hey stavo cercando di usare il tuo codice con regex e mi è capitato di avere un errore su stackoverflow.com/questions/16087351/… . Pensi di poter aiutare? :)
psharma

@psharma Niente a che fare con bootstrap o tooltip. Il tuo errore è la dichiarazione della regola quando hai ottenuto una risposta alla tua domanda. il messaggio di errore diceva: i termini non sono definiti!
Adrian P.

Per qualche motivo, questa è l'unica soluzione che ha funzionato per me. Grazie!
suchanoob

2

È così che l'ho realizzato. Ma implica apportare 2 modifiche allo script di convalida (ho ottenuto il codice per bootstrap 1.4 qui e poi l'ho modificato - http://mihirchitnis.net/2012/01/customizing-error-messages-using-jquery-validate-plugin- per-twitter-bootstrap / )

La mia chiamata per convalidare:

    $("#loginForm").validate({
  errorClass: "control-group error",
  validClass: "control-group success",
  errorElement: "span", // class='help-inline'
  highlight: function(element, errorClass, validClass) {
    if (element.type === 'radio') {
        this.findByName(element.name).parent("div").parent("div").removeClass(validClass).addClass(errorClass);
    } else {
        $(element).parent("div").parent("div").removeClass(validClass).addClass(errorClass);
    }
  },
  unhighlight: function(element, errorClass, validClass) {
    if (element.type === 'radio') {
        this.findByName(element.name).parent("div").parent("div").removeClass(errorClass).addClass(validClass);
    } else {
        $(element).parent("div").parent("div").removeClass(errorClass).addClass(validClass);
    }
  }
});

Quindi è necessario modificare 2 cose in jquery.validate.js
1. applicare questa correzione - https://github.com/bsrykt/jquery-validation/commit/6c3f53ee00d8862bd4ee89bb627de5a53a7ed20a
2. Dopo la riga 647 (nella funzione showLabel, creare la parte dell'etichetta ) dopo la riga .addClass(this.settings.errorClass)aggiungi riga: .addClass("help-inline")
qualcuno può forse trovare un modo per applicare la seconda correzione nella funzione di convalida, ma non ho trovato un modo, poiché showLabel viene chiamato dopo l'evidenziazione.


2

Questo è ciò che ho inserito nella mia convalida per conformarmi alle linee guida di Twitter Bootstrap. Il messaggio di convalida dell'errore viene inserito in a <span class=help-inline>e vogliamo evidenziare il contenitore esterno come erroro success:

errorClass:'help-inline',
errorElement:'span',
highlight: function (element, errorClass, validClass) {
$(element).parents("div.clearfix").addClass('error').removeClass('success');
},
unhighlight: function (element, errorClass, validClass) {
$(element).parents(".error").removeClass('error').addClass('success');
}

2

Ecco un aggiornamento all'eccellente risposta di Kenny Meyer sopra . Ci sono stati un paio di problemi che gli hanno impedito di funzionare per me, che ho affrontato in questo snippet:

showErrors: function (errorMap, errorList) {
        $.each(this.successList, function (index, element) {
            return $(element).popover("destroy");
        });

        $.each(errorList, function (index, error) {
            var ele = $(error.element); //Instead of referencing the popover directly, I use the element that is the target for the popover

            ele.popover({
                    trigger: "manual",
                    placement: "top",
                    content: function(){ //use a function to assign the error message to content
                        return error.message
                    },
                    template: '<div class="popover"><div class="arrow"></div><div class="popover-inner"><div class="popover-content"><p></p></div></div></div>'
            });

            //bs.popover must be used, not just popover
            ele.data("bs.popover").options.content = error.message;

            return $(error.element).popover("show");
        });
    }

Grazie per l'iniziativa. Il codice è cambiato molto come posso vedere :-)
Kenny Meyer

1

Non sono sicuro che questo sia rilevante per la discussione perché il poster originale richiedeva degli hook per mostrare / nascondere i popover bootstrap.

Stavo cercando una semplice convalida e i popover non avevano importanza. Un post correlato e il primo nei risultati di ricerca di Google è già stato contrassegnato come duplicato di questa domanda. Quindi aveva senso menzionare questo eccellente jqValidation JS di @ ReactiveRaven, giustamente chiamato jqBootstrapValidation, che si sposa bene con Twitter Bootstrap. L'installazione richiede solo pochi minuti. Scarica qui .

Spero che questo aggiunga valore.


1

tl; dr evita di dover enumerare i popover espliciti utilizzando una mappa hash per memorizzare gli id ​​degli elementi e creando popover al volo (mashup Jeffrey Gilbert e gli approcci di Kenny Meyer).

Ecco la mia opinione, che risolve il problema dello sfarfallio menzionato da altri, ma a differenza della risposta di @Jeffrey Gilbert, non utilizza una lista ( errorStates) ma utilizza piuttosto una mappa degli errori . Mappe hash FTW. Penso di ricordare di aver letto da qualche parte che ogni problema in CS può essere risolto con una mappa hash :)

var err_map = new Object();     // <--- n.b.
$("form#set_draws").validate({
  rules: {
    myinput: { required: true, number: true },
  },
  showErrors: function(errorMap, errorList) {
    $.each(this.successList, function(index, value) {
      if (value.id in err_map)
      {
        var k = err_map[value.id];
        delete err_map[value.id]; // so validation can transition between valid/invalid states
        k.popover("hide");
      }
    });
    return $.each(errorList, function(index, value) {
      var element = $(value.element);
      if( ! (value.element.id in err_map) ) {
        var _popover = element.popover({
          trigger: "manual",
                 placement: "top",
                 content: value.message,
                 template: "<div class=\"popover\"><div class=\"arrow\"></div><div class=\"popover-inner\"><div class=\"popover-content\"><p></p></div></div></div>"
        });
        _popover.data("popover").options.content = value.message;
          err_map[value.element.id] = _popover;
        return err_map[value.element.id].popover("show");
      }
    });
  }
});

Grazie a tutti gli altri che hanno pubblicato idee su questo.



0

Se si utilizza il codice Kenny Meyer sopra per i popup, fare attenzione che le regole che controllano il contenuto di un campo ma non è richiesto come un URL valido faranno sì che il popup non scompaia dopo aver cancellato il campo. Vedi sotto onkeyup per la soluzione. Se qualcuno ha una soluzione migliore, per favore pubblica.

onkeyup: function(element, event) {
            if($(element).valid())  {
                return $(element).popover("hide");
            }
        }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.