Search code examples
javascripthtmlsubmitpreventdefaultstoppropagation

Bootstrap form doesn't cancel submission when validation failed


I'm trying to create a form which will send an email to the user on submit.

The thing is that I used Bootstrap's form template and when I submit it with phone and mail wrong values (phone number even empty), the email is sent anyway (with 200 ok) and a success alert is showing.

Here is my HTML code:

<form class="needs-validation" novalidate id="paymentForm">
                        <div class="row">
                            <div class="col-md-6 mb-3">
                                <label for="firstName">First Name</label>
                                <input type="text" class="form-control" name="firstName" id="firstName" placeholder="" value="" required>
                                <div class="invalid-feedback">
                                    required Feild
                                </div>
                            </div>
                            <div class="col-md-6 mb-3">
                                <label for="lastName">Lasr Name</label>
                                <input type="text" class="form-control" name="lastName" id="lastName" placeholder="" value="" required>
                                <div class="invalid-feedback">
                                    required Feild
                                </div>
                            </div>
                        </div>

                        <div class="mb-3">
                            <label for="email">Email</label>
                            <input type="email" class="form-control" value="" name="email" id="email" placeholder="you@example.com" required>
                            <div class="invalid-feedback">
                                please enter a valid mail address
                            </div>
                        </div>

                        <div class="mb-3">
                            <label for="phone">Phone Number</label>
                            <input type="tel" class="form-control" value="" name="phone" placeholder="example: 050-1111111" pattern="[0]{1}[5]{1}[0-9]{8}" id="phone" required>
                            <div class="invalid-feedback">
                                please provide a valid phone number
                            </div>
                        </div>

                        <div class="mb-3">
                            <label for="address"> address</label>
                            <input type="text" class="form-control" name="address" id="address" placeholder="" required>
                            <div class="invalid-feedback">
                              please provide your address
                            </div>
                        </div>
                        <hr class="mb-4">

                        <h4 class="mb-3">payment method</h4>
                        <div class="d-block my-3">
                            <div class="custom-control custom-radio">
                                <input id="cash" value="cash" value="cash" name="paymentMethod" type="radio" class="custom-control-input" required checked>
                                <label class="custom-control-label" for="cash">cash</label>
                            </div>
                            <div class="custom-control custom-radio">
                                <input id="bit" value="bit" value="bit" name="paymentMethod" type="radio" class="custom-control-input" required>
                                <label class="custom-control-label" for="bit">Bit</label>
                            </div>
                        </div>
                        <div class="invalid-feedback">
                            please choose method
                        </div>

                        <hr class="mb-4">
                        <button class="btn btn-primary btn-lg btn-block" type="submit">continue to checkout</button>

                    </form>

and here is my js:

(function() {
    'use strict'
    window.addEventListener('load', function() {       
        var forms = document.getElementsByClassName('needs-validation')       
        Array.prototype.filter.call(forms, function(form) {
            form.addEventListener('submit', function(event) {

                var radioValue = $('#paymentForm input:radio:checked').val()
                if (form.checkValidity() === false) {
                    event.preventDefault();
                    event.stopPropagation();
                }
                form.classList.add('was-validated')
                var orderNumber = generateId();
                var cName = $('#firstName').val() + " " + $('#lastName').val()
                var cEmail = $('#email').val()
                var cPhone = $('#phone').val()
                var cAddress = $('#address').val()
                var cSumToPay = parseInt(localStorage.getItem("totalPrice"));
                var cProducts = JSON.parse(localStorage.getItem("products") || "[]");
                cProducts = cProducts.map(Object.values);                   
                cProducts = cProducts.join(' ');
                console.log(cProducts);
                var templateParams = {
                    order_number: orderNumber,
                    customer_name: cName,
                    products: cProducts,
                    addres: cAddress,
                    phone: cPhone,
                    customer: cEmail,
                    payment_Methode: radioValue,
                    customer_sum: cSumToPay
                };
                emailjs.send('gmail', 'orderconfirmation', templateParams)
                    .then(function(response) {
                        console.log('SUCCESS!', response.status, response.text);
                        alert('Yey! Your email was sent :)');           
                    }, function(error) {
                        console.log('error');
                        alert(error);
                    });
                event.preventDefault();
            }, false)
        })
    }, false)

}())

I would be thankful if you guys can help me!!!


Solution

  • This section appears to be your only check for validation:

                if (form.checkValidity() === false) {
                    event.preventDefault();
                    event.stopPropagation();
                }
    

    However, event.preventDefault() and event.stopPropagation() are not going to prevent the code from falling through to the next section. You can do that by including a return at this point

                if (form.checkValidity() === false) {
                    event.preventDefault();
                    event.stopPropagation();
                    return false;
                }
    

    or you can wrap the rest of your code in the else of your conditional

                if (form.checkValidity() === false) {
                    event.preventDefault();
                    event.stopPropagation();
                } else {
                    // your email handling code
                }
    

    Note: your event.preventDefault() is useful to stop the submit button from performing its default behavior of submitting the form and event.stopPropagation() will just keep the event from bubbling up to parent elements (which you likely don't need). See: https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault and https://developer.mozilla.org/en-US/docs/Web/API/Event/stopPropagation

    In any case, you do not need two event.preventDefault() calls if you place a single one at the top of your event listener, e.g.

    form.addEventListener('submit', function(event) {
        event.preventDefault();
        ...