2

I'm using the latest version of jquery-validation (1.19.0) in the web app based on Laravel (5.7x) and have this issue.

In case of blank (not filled) <input type="email" name="email"> it shows me an error Enter a valid Email. This input is not required, so I need a validation only in case of filling this input. Thanks!

HTML part

<form action="{{ route('posts-listing.store') }}" method="POST" class="m-form m-form--label-align-right" id="m_post_submit">
  <div class="modal-body">
    @csrf
    <div class="form-group m-form__group row">
      <label class="col-md-4 col-form-label">Name: <span class="text-danger">*</span></label>
      <div class="col-md-8">
        <input class="form-control m-input" type="text" placeholder="Enter name" name="name" autofocus>
      </div>
    </div>
    <div class="form-group m-form__group row">
      <label class="col-md-4 col-form-label" for="phone_country">Phone Number: <span class="text-danger">*</span></label>
      <div class="col-md-8">
        <div class="input-group m-input-group">
          <div class="input-group-prepend">
            <select class="form-control m-bootstrap-select m_selectpicker" name="phone_country" id="phone_country">
                <option value="1" selected title="SK">Slovakia (+421)</option>
                <option data-divider="true"></option>
                <option value="2" title="CZ">Czech (+420)</option>
            </select>
          </div>
          <input type="text" class="form-control" id="m_inputmask_phone" name="phone_number" placeholder="Enter phone number">
        </div>
      </div>
    </div>
    <div class="form-group m-form__group row">
      <label class="col-md-4 col-form-label">E-mail address:</label>
      <div class="col-md-8">
        <input class="form-control m-input" type="email" placeholder="Enter your email" name="email" autocomplete="off" required="false">
      </div>
    </div>
    <div class="form-group m-form__group row">
      <label class="col-md-4 col-form-label">Note:</label>
      <div class="col-md-8">
        <textarea class="form-control m-input" id="m_autosize_1" rows="3" placeholder="Enter your note..." name="notes"></textarea>
      </div>
    </div>
  </div>
  <div class="modal-footer">
    <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
    <button type="submit" class="btn crud-submit btn-primary">{{ Auth::user()->hasRole('agent') ? "Add new" : "Send" }}</button>
  </div>
</form>

JavaScript --> this is a part of the whole JS file with other functions

    $('#m_post_submit').validate({
      rules: {
        name: {
          required: true
        },
        phone_number: {
          required: true,
          minlength: 12
        },
        email: {
          required: false
          email: true
        }
      },
      submitHandler: function(form) {
        form.ajaxSubmit({
          type: 'post',
          url: form.attr('action'),
          data: form.serialize(),
          success: function() {
            btn.removeClass('m-loader m-loader--right m-loader--light').attr('disabled', false);
            location.reload();
          }
        });
        return false;
      }
    });
Jakub Adamec
  • 953
  • 16
  • 22
  • Change the type from `email` and the rules from `email` and that'll allow it to be submitted – Isaac Dec 19 '18 at 16:20
  • In that case the validation will be removed completely... I need it applied only in case of filling the email input. – Jakub Adamec Dec 19 '18 at 16:22
  • Using `type="email"` is practically pointless when using the jQuery Validate plugin. This plugin disables all HTML5 validation, and the field behaves no differently than with `type="text"`. If you think it's supposed to be used as a HTML5 validation "fallback" when JavaScript is disabled, that's also pointless since your Ajax submit will not work without JavaScript. – Sparky Dec 19 '18 at 17:34

2 Answers2

3

Oh well, problem was in the main settings of used site template Metronic. There's a validator.addMethod for type="email" by default and looks like this. After removing it works correctly!

/theme/default/src/js/framework/components/plugins/forms/jquery-validation.init.js

jQuery.validator.addMethod("email", function(value, element) {
    if (/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/.test(value)) {
        return true;
    } else {
        return false;
    }
}, "Please enter a valid Email.");
Jakub Adamec
  • 953
  • 16
  • 22
  • That’s because this rule is not constructed properly. There’s another line of code that’s required in order to ensure the field is optional. **Since you didn’t include this in your OP, how could anyone have possibly known about this custom rule in order to answer your question?!** – Sparky Dec 20 '18 at 15:39
  • I fully understand you, but to be honest I didn't know about this custom rule in website template [Metronic](https://themeforest.net/item/metronic-responsive-admin-dashboard-template/4021469). Thanks for your time. – Jakub Adamec Dec 20 '18 at 19:35
  • I know. Just seems like we were all sent off in different directions, first from lack of enough code in OP, and secondly from a missing comma within edited OP. – Sparky Dec 20 '18 at 19:45
1

You have not properly initialized the jQuery Validate plugin, therefore it seems like HTML5 validation is taking over thanks to the type="email" attribute.

Your code:

$('#m_post_submit').click(function(e) {
    e.preventDefault();
    ....
    form.validate({ ... });
    ....
    form.ajaxSubmit({ ... });
});
  1. You should not have .validate() inside of a click event handler. Just call it once on page load and the click will be captured automatically. The .validate() method is primarily used for initialization of the plugin on your form, not for testing validation.

  2. The Ajax belongs inside of the submitHandler function of the plugin.

Code should look a lot more like this:

$(document).ready(function() {

    $('#yourform').validate({ // <- initializes plugin
        rules: {
            email: {
                email: true
            }
        },
        submitHandler: function(form) { // <- made for AJAX
            // AJAX goes here
            form.ajaxSubmit({ .... });
            return false;
        }
    });

});

Otherwise, everything seems to be working properly. The email field is only validated when it contains a value:

DEMO: jsfiddle.net/shLx3b65/


NOTE: Using type="email" is practically pointless when using the jQuery Validate plugin. This plugin disables all HTML5 validation, and the field behaves no differently than with type="text". It's also pointless as a HTML5 validation "fallback" when JavaScript is disabled since your Ajax will not work without JavaScript anyway.


EDIT:

As per updated OP, there is a syntax error:

email: {
    required: false // <- COMMA MISSING HERE
    email: true
}

This syntax error breaks the JavaScript and the HTML5 validation takes over thanks to the type="email" attribute... much like I stated in the very first paragraph of this answer.

Upon adding this missing comma, everything works as expected:

jsfiddle.net/8wxo4cdy/

Sparky
  • 98,165
  • 25
  • 199
  • 285
  • Thank you, this code improvement looks really good, but still didn' fix my issue. :( Anyway, I tried to copy whole parts of my code into jsfiddle and it works there! So problem must be elsewhere... By which Laravel part or plugin this can be affected, please? – Jakub Adamec Dec 19 '18 at 18:46
  • @JakubAdamec, your problem is elsewhere. Any JavaScript console errors? What happens when you change field into a `type="text"`? So many things could be going wrong that are not part of your OP. Why not post a more complete demo in the OP. All relevant HTML markup of the form would be a good start. – Sparky Dec 19 '18 at 18:50
  • And since Laravel is writing the markup, have you inspected the browser DOM to see the actual HTML? – Sparky Dec 19 '18 at 18:53
  • No JS console errors. Nothing has changed after editing `type`, but I figured that validation is active also in case I disable rules from the JS part and have only set `type="email"`. In case of disabled JS rules and set `type="text"`, the validation is disabled completely (but that's not what I want). – Jakub Adamec Dec 19 '18 at 19:50
  • **UPDATED OP** - I add the whole form and my current JS. – Jakub Adamec Dec 19 '18 at 20:21
  • @JakubAdamec, in case of disabled JavaScript, there would be no Ajax submit either, so any issue of client-side validation is completely moot. – Sparky Dec 20 '18 at 04:55
  • @JakubAdamec, it's pointless to show us your Laravel server-side code. Show the rendered markup as per the browser DOM... that is what we need to troubleshoot because that is only what the JavaScript is seeing. – Sparky Dec 20 '18 at 04:57
  • @JakubAdamec, you have a syntax error: you'll need a comma between your two `email` rules. Otherwise, it's working fine: https://jsfiddle.net/8wxo4cdy/ However without the comma, JavaScript breaks and [HTML5 validation takes over](https://jsfiddle.net/8wxo4cdy/1/), exactly like I stated in the very first paragraph of this answer. – Sparky Dec 20 '18 at 05:08
  • Well, I found the solution. Please see my answer to this topic... Many thanks for your time @Sparky ! – Jakub Adamec Dec 20 '18 at 06:29
  • @JakubAdamec, it would have been helpful to post code without syntax errors in your OP. And I don't know how was anyone here supposed to know that the default `email` rule was being replaced by a custom rule that was not written properly? – Sparky Dec 20 '18 at 19:29