jQuery 유효성 검사 알림을 위해 Twitter Bootstrap 팝 오버를 사용하는 방법은 무엇입니까?


84

부트 스트랩을 사용하여 팝 오버를 쉽게 표시 할 수 있으며 표준 jQuery 유효성 검사 플러그인 또는 jQuery 유효성 검사 엔진을 사용하여 유효성 검사를 수행 할 수도 있지만 하나를 다른 것으로 공급하는 방법을 알 수 없습니다.

내가 필요한 것은 알림을 표시하고 메시지와 대상 요소를 팝 오버로 전달하는 클로저를 제공하려고 할 때 유효성 검사기가 호출하는 후크입니다. 이것은 일종의 의존성 주입처럼 보입니다.

이론적으로는 모두 훌륭하지만 그 후크가 어디에 있는지 또는 유효성 검사 엔진에 있는지 여부를 알 수 없습니다. 둘 다 내가 원하는 모든 것이 오류 유형 (반드시 메시지 텍스트가 필요하지는 않음) 및 관련 요소 일 때 배치, 래퍼, 스타일에 대한 모든 종류의 정교한 옵션으로 알림을 표시하는 데 책임을지는 것 같습니다. 에. 개별 알림이 아닌 전체 양식에 대한 후크를 찾았습니다.

동적으로 생성 된 양식과 잘 어울리기 때문에 규칙을 정의하기 위해 클래스를 사용하는 유효성 검사 시스템을 훨씬 선호합니다.

누구든지 해결책이나 더 나은 아이디어가 있습니까?

답변:


21

highlightshowErrors jQuery Validator 옵션을 살펴보면 부트 스트랩 팝 오버를 트리거하는 사용자 지정 오류 하이라이트에 연결할 수 있습니다.


훌륭합니다. 감사합니다. 강조 표시 및 강조 표시 해제는 내가 찾던 것입니다.
Synchro

80

다음은 실습 예제입니다.

$('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); 
    }
});

여기에 이미지 설명 입력

실제로 부트 스트랩 팝 오버를 사용하지는 않지만 정말 멋져 보이고 달성하기 쉽습니다.

최신 정보

따라서 팝 오버 유효성 검사를하려면 다음 코드를 사용할 수 있습니다.

$("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");
    });
  }
});

You get something like this:

enter image description here

Check out the jsFiddle.


3
Upvoted because this is in the direction of what I was looking for. :-) See my answer for a variant.
namin

What to do if it is a multistage form
Tachyons

4
Just a quick note that with the latest version of Bootstrap there is not longer a .data("popover") key. Perhaps to avoid collision they have changed the key to "bs.popover". Took me a while to figure out why I was getting an undefined error. So now you'll need to use _popover.data("bs.popover").options.content = value.message; in the code above.
davidethell

How can i display popup on other error type other than required fields. I mean to say how can i customize it to display error only on specific rules.
arjun

There's actually a little problem you can easily check out in the jsFiddle as well. If the field is not required and some rule is broken, the popover shows up BUT if I empty the field and focus on another field, the popover is still there. The first loop on the successList is never called, so the popover is never in a "hide" state after it gets in a "show" state. Is there anything we can do about it ?
G4bri3l

9

Chris Fulstow had it right, but it still took me a while, so heres the complete code:

This shows the popover on error, and hides the default error labels:

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

This sets up the popover. The only thing you need from this is trigger: 'manual'

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

The title and content attributes passed in to popover weren't working, so I specified them inline in my #password input with data-content='Minimum 5 characters' and data-original-title='Invalid Password'. You also need rel='popover' in your form.

This works, but the popover flickers upon unselecting. Any idea how to fix that?


6

Here's a follow up to the excellent suggestion from Varun Singh which prevents the "flicker" issue of the validation constantly trying to "show" even though the popup is already present. I've simply added an error states array to capture which elements are showing errors and which aren't. Works like a charm!

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'
});

This was the only answer on this page that worked for me. Shame it's not been voted up more.
alastairs

1
Doesn't this mean you need to define an explicit popover for every single field you want to validate? If so that's nuts.
g33kz0r

For most use cases, I would expect this is perfectly acceptable. If you have a more optimal solution, feel free to add it :)
Jeffrey Gilbert


3

I prefer to change the CSS of bootstrap. Just added the classes of jQuery validate in the right place. field-validation-error and 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;
}

This approach looks best for me :) . This is also what i was thinking
Freshblood

3

This is how I did it with Bootstrap 2.x and 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

Please take a look at the following:
- https://gist.github.com/3030983
I think it's the simplest of all.

EDIT

Code from link:

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

        });

    }

});

Many thanks for the heads up! See down my version for Bootstrap but with Tooltips. In my opinion it's more elegant than popovers.
Adrian P.

3

Many thanks for the heads up! Here is my version for Bootstrap but with Tooltips. In my opinion it's more elegant than popovers. I know the question was for popovers so please do not vote down for this reason. Maybe somebody will like it this way. I love when I'm searching for something and I found new ideas on Stackoverflow. Note: no markup on form is necessary.

    $('#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
I tried to use your approach, but I was starting to get and error. ant he problem is if you use Jquery UI you will get conflict because both use tooltip. I know there is a solution for that, but just want let others users to know that.
Richard Pérez

+1 For jQuery UI heads up! You'll have to configure your custom download (jQueryUI or Bootstrap) to NOT include Tooltip JS functions. It will be a conflict anyway for any tooltip if you failed to do so.
Adrian P.

hey there I was trying to use your code with regex and happen to have an error at stackoverflow.com/questions/16087351/… . Do you think you can help? :)
psharma

@psharma Nothing to do with bootstrap or tooltip. Your error is your rule declaration as you got an answer on your question. the error message said: terms is undefined!
Adrian P.

For some reason, this is the only solution that worked for me. Thanks!
suchanoob

2

This is how I made it happen. But it involves making 2 changes to the validate script (I got the code for bootstrap 1.4 here and then modified it - http://mihirchitnis.net/2012/01/customizing-error-messages-using-jquery-validate-plugin-for-twitter-bootstrap/)

My call to validate:

    $("#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);
    }
  }
});

Then you need to change 2 things in jquery.validate.js
1. apply this fix - https://github.com/bsrykt/jquery-validation/commit/6c3f53ee00d8862bd4ee89bb627de5a53a7ed20a
2. After line 647 (in the showLabel function, create label part) after line .addClass(this.settings.errorClass) add line: .addClass("help-inline")
Someone can maybe find a way to apply the second fix in the validate function, but I havent found a way, since showLabel is called after highlight.


2

This is what I put in my validate to conform to the Twitter Bootstrap guidelines. The error validation message is put in a <span class=help-inline> and we want to highlight the outer container as an error or 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

Here is an update to Kenny Meyer's excellent answer above. There were a couple of issues that prevented it from working for me, which I have addressed in this 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");
        });
    }

Thank you for the initiative. The code has changed a lot as I can see :-)
Kenny Meyer

1

Not sure if this is relevant to the discussion because the original poster asked for hooks to show/hide bootstrap popovers.

I was looking for simple validation and popovers didn't matter. A related post and the first in google search results has already been marked duplicate of this question. So it made sense to mention this excellent @ReactiveRaven's jqValidation JS, aptly called jqBootstrapValidation, that weds well with Twitter Bootstrap. Setup takes a few minutes only. Download here.

Hope this adds value.


1

tl;dr avoid needing to enumerate explicit popovers by using a hash map to store the ids of the elements, and creating popovers on-the-fly (mashup Jeffrey Gilbert and Kenny Meyer's approaches).

Here's my take, which fixes the flickering problem mentioned by others, but unlike @Jeffrey Gilbert's answer, does not use a list (errorStates) but rather uses an error map. Hash maps FTW. I think I remember reading somewhere that every problem in CS can be solved with a hash map :)

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

Thanks to all others who posted ideas on this.



0

If using the above Kenny Meyer code for popups, beware that rules that check a field's content but isn't required such as a valid URL will cause the popup to not disappear upon clearing the field. See below onkeyup for solution. If anyone has a better solution, please post.

onkeyup: function(element, event) {
            if($(element).valid())  {
                return $(element).popover("hide");
            }
        }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.