barbajs / barba

Create badass, fluid and smooth transitions between your website’s pages
https://barba.js.org/
MIT License
11.62k stars 474 forks source link

Validate.js not recognizing form loaded using barba #231

Closed rachste closed 6 years ago

rachste commented 6 years ago

Hello all!

I'm a newcomer to Javascript, but I think I get what's happening - I'm just unsure of how to go about fixing it myself.

If I access the page directly, e.g. http://mydomain.com/contact/, then everything works as expected.

If the form is loaded using barba, the data submitted through the form is appended to the URL (http://mydomain.com/contact/?name=test&_replyto=test%40test.com&message=test), an email isn't sent out to me, and my success message doesn't load.

I noticed when I access the page directly that novalidate="novalidate" is added to <form>. This doesn't happen when the form is loaded using barba. My thinking is that my custom Javascript for Validate.js isn't picking up my form since it's being loaded dynamically.

I tried out a few solutions from the web, but nothing has worked for me, unfortunately. Any help is appreciated!

My Formspree form:

<main>
    <p>
        Have an idea brewing? Let's chat!
    </p>

    <p>
        If you run into any problems with the form, <a href="mailto:">reach out</a> to me directly.
    </p>

    <!-- Hidden message to show if form is successful. -->
    <p id="submit-success" class="hidden">
        Off it goes! Thanks so much. I'll be in touch as soon as possible.
    </p>

    <p>|</p>

    <!-- Formspree contact form -->
    <form id="contact-form">
        <div class="form-input">
            <label for="name">What's your name?</label>
            <input type="text" name="name" required />
        </div>
        <div class="form-input">
            <label for="email">And your email?</label>
            <input type="email" name="_replyto" required />
        </div>
        <div class="form-input">
            <label for="message">Your message:</label>
            <textarea name="message" required></textarea>
        </div>
        <input type="submit" value="Send" />
    </form>

    <!-- Hidden message to show if user encounters errors. -->
    <p id="submit-errors" class="hidden">
      Hmmm, it looks like an error occurred. Try again.
    </p>
</main>

Here's my custom Javascript:

/* Barba transition */
document.addEventListener("DOMContentLoaded", function() {
    var FadeTransition = Barba.BaseTransition.extend({
      start: function() {
        Promise
          .all([this.newContainerLoading, this.fadeOut()])
          .then(this.fadeIn.bind(this));
      },

      fadeOut: function() {
        this.oldContainer.classList.toggle('fade-out');
        return new Promise(function(resolve, reject) {
            setTimeout(function() {
               resolve();
           }, 500);
        });
      },

      fadeIn: function() {
        $(window).scrollTop(0); // scroll to top 

        this.newContainer.classList.toggle('fade-in');
        this.done();
      }
    });

    Barba.Pjax.getTransition = function() {
      return FadeTransition;
    };
});

Barba.Pjax.start();

/* Validate.js */
$("#contact-form").validate({
  submitHandler: function(form) {
    $.ajax({
      url: "//formspree.io/me@me.com", 
      method: "POST",
      data: {
        name: $(form).find("input[name='name']").val(),
        _replyto: $(form).find("input[name='_replyto']").val(),
        message: $(form).find("textarea[name='message']").val()
      },
      dataType: "json",
      success: function() {
        $("#submit-success").fadeIn();
        $("#hide-on-submit-success").fadeOut();
      },
      error: function() {
        $("#submit-errors").fadeIn();        
      }
    });
  }
});
khaiknievel commented 6 years ago

Hey. You are thinking in the right direction. Since it 's being loaded dynamically, $('#contact-form') is being replaced, hence lose its refs.

You will need to tell Validate.js pick up your form again after the Barba replace the new container.

Attach a listener when a new page is ready to tell Validate.js about the new form.

Reading http://barbajs.org/events.html should help you start with ya solution.

Hope that helps. Cheers.

Uranbold commented 6 years ago

@khaiknievel Can you please give more information. Example: I'm using the Owl Carousel and this need to be reinit on that Events?

Some JavaScript plugins don't have the Reinit function and how can i achive this?

Thanks.

khaiknievel commented 6 years ago

@Uranbold For example.


document.addEventListener('DOMContentLoaded', function () {
  $("#contact-form").validate()
})

// Simply re-init.
// The plugin does not need to have the reinit function.
// 
// @see http://barbajs.org/events.html
Barba.Dispatcher.on('newPageReady', function(currentStatus, oldStatus, container) {
  $("#contact-form").validate()
});

See: http://barbajs.org/events.html

In your example case, simply call the init method for the Owl Carousel.