简体   繁体   English

在使用PHP和AJAX的Bootstrap联系表顶部显示错误消息

[英]Displaying Error message on top of Bootstrap contact form with PHP and AJAX

Heres the Contact form page that Im having a problem displaying an error message. 这是我在显示错误消息时遇到问题的联系表单页面 When I submit the form, it redirects to a blank page (and was able to receive an email from the form) instead of displaying a message on top of the form. 当我提交表单时,它重定向到空白页(并且能够从表单接收电子邮件),而不是在表单顶部显示消息。

On the contact.php blank page, it looks like AJAX is not doing anything to display the message inside the messages class - contact.php空白页上,看起来AJAX没有做任何事情来显示message类中的messages -

// if requested by AJAX request return JSON response
if (empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
    $encoded = json_encode($responseArray);
    header('Content-Type: application/json');
    return $encoded;
}
// else just display the message
else {
    return $responseArray['message'];
}

form - 表格-

<form id="contact-form" method="post" action="contact.php" role="form">
<div class="messages"></div> <--------- messages to display
...
</form>

Configuration contact.php - 配置contact.php

<?php
// an email address that will be in the From field of the email.
$from = 'Contact form';

// an email address that will receive the email with the output of the form
$sendTo = $_POST['email'];

// subject of the email
$subject = 'New message from contact form';

// form field names and their translations.
// array variable name => Text to appear in the email
$fields = array('name' => 'Name', 'surname' => 'Surname', 'phone' => 
'Phone', 'email' => 'Email', 'message' => 'Message'); 

// message that will be displayed when everything is OK :)
$okMessage = 'Contact form successfully submitted. Thank you, I will get back to you soon!';

// If something goes wrong, we will display this message.
$errorMessage = 'There was an error while submitting the form. Please try again later';

// if you are not debugging and don't need error reporting, turn this off by 
error_reporting(0);
error_reporting(E_ALL & ~E_NOTICE);

try
{

if(count($_POST) == 0) throw new \Exception('Form is empty');

$emailText = "You have a new message from your contact 
form\n=============================\n";

foreach ($_POST as $key => $value) {
    // If the field exists in the $fields array, include it in the email 
    if (isset($fields[$key])) {
        $emailText .= "$fields[$key]: $value\n";
    }
}

// All the neccessary headers for the email.
$headers = array('Content-Type: text/plain; charset="UTF-8";',
    'From: ' . $from,
    'Reply-To: ' . $from,
    'Return-Path: ' . $from,
);

// Send email
mail($sendTo, $subject, $emailText, implode("\n", $headers));

$responseArray = array('type' => 'success', 'message' => $okMessage);
}
catch (\Exception $e)
{
$responseArray = array('type' => 'danger', 'message' => $errorMessage);
}


// if requested by AJAX request return JSON response
if (empty($_SERVER['HTTP_X_REQUESTED_WITH']) &&  strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
$encoded = json_encode($responseArray);

header('Content-Type: application/json');

return $encoded;
}
// else just display the message
else {
return $responseArray['message'];
}

AJAX - contact.js AJAX- contact.js

$(function () {

$('#contact-form').validator();

// when the form is submitted
$('#contact-form').on('submit', function (e) {

    // if the validator does not prevent form submit
    if (e.isDefaultPrevented()) {
        var url = "contact.php";

        // POST values in the background the the script URL
        $.ajax({
            type: "POST",
            url: url,
            data: $(this).serialize(),
            success: function (data)
            {
                // data = JSON object that contact.php returns

                // we recieve the type of the message: success x danger and apply it to the 
                var messageAlert = 'alert-' + data.type;
                var messageText = data.message;

                // let's compose Bootstrap alert box HTML
                var alertBox = '<div class="alert ' + messageAlert + ' alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>' + messageText + '</div>';

                // If we have messageAlert and messageText
                if (messageAlert && messageText) {
                    // inject the alert to .messages div in our form
                    $('#contact-form').find('.messages').html(alertBox);
                    // empty the form
                    $('#contact-form')[0].reset();
                }
            }
        });
    }
});
});

validator.js 验证器

+function ($) {
'use strict';

// VALIDATOR CLASS DEFINITION
// ==========================

function getValue($el) {
return $el.is('[type="checkbox"]') ? $el.prop('checked'):
       $el.is('[type="radio"]')    ? !!$('[name="' + $el.attr('name') + 
'"]:checked').length :
                                     $el.val()
}

var Validator = function (element, options) {
this.options    = options
this.validators = $.extend({}, Validator.VALIDATORS, options.custom)
this.$element   = $(element)
this.$btn       = $('button[type="submit"], input[type="submit"]')
                    .filter('[form="' + this.$element.attr('id') + '"]')
                    .add(this.$element.find('input[type="submit"], button[type="submit"]'))

this.update()

this.$element.on('input.bs.validator change.bs.validator 
focusout.bs.validator', $.proxy(this.onInput, this))
this.$element.on('submit.bs.validator', $.proxy(this.onSubmit, this))
this.$element.on('reset.bs.validator', $.proxy(this.reset, this))

this.$element.find('[data-match]').each(function () {
  var $this  = $(this)
  var target = $this.data('match')

  $(target).on('input.bs.validator', function (e) {
    getValue($this) && $this.trigger('input.bs.validator')
  })
   })

this.$inputs.filter(function () { return getValue($(this)) 
}).trigger('focusout')

this.$element.attr('novalidate', true) // disable automatic native validation
this.toggleSubmit()
    }

 Validator.VERSION = '0.11.5'

 Validator.INPUT_SELECTOR = ':input:not([type="hidden"], [type="submit"], [type="reset"], button)'

 Validator.FOCUS_OFFSET = 20

 Validator.DEFAULTS = {
delay: 500,
html: false,
disable: true,
focus: true,
custom: {},
errors: {
  match: 'Does not match',
  minlength: 'Not long enough'
 },
 feedback: {
  success: 'glyphicon-ok',
  error: 'glyphicon-remove'
 }
 }

 Validator.VALIDATORS = {
 'native': function ($el) {
  var el = $el[0]
  if (el.checkValidity) {
    return !el.checkValidity() && !el.validity.valid && (el.validationMessage || "error!")
  }
  },
'match': function ($el) {
  var target = $el.data('match')
  return $el.val() !== $(target).val() && Validator.DEFAULTS.errors.match
},
'minlength': function ($el) {
  var minlength = $el.data('minlength')
  return $el.val().length < minlength && Validator.DEFAULTS.errors.minlength
  }
 }

 Validator.prototype.update = function () {
 this.$inputs = this.$element.find(Validator.INPUT_SELECTOR)
  .add(this.$element.find('[data-validate="true"]'))
  .not(this.$element.find('[data-validate="false"]'))

 return this
 }

 Validator.prototype.onInput = function (e) {
 var self        = this
 var $el         = $(e.target)
 var deferErrors = e.type !== 'focusout'

 if (!this.$inputs.is($el)) return

 this.validateInput($el, deferErrors).done(function () {
  self.toggleSubmit()
 })
 }

 Validator.prototype.validateInput = function ($el, deferErrors) {
 var value      = getValue($el)
 var prevErrors = $el.data('bs.validator.errors')
 var errors

 if ($el.is('[type="radio"]')) $el = this.$element.find('input[name="' + $el.attr('name') + '"]')

 var e = $.Event('validate.bs.validator', {relatedTarget: $el[0]})
 this.$element.trigger(e)
 if (e.isDefaultPrevented()) return

 var self = this

 return this.runValidators($el).done(function (errors) {
  $el.data('bs.validator.errors', errors)

  errors.length
    ? deferErrors ? self.defer($el, self.showErrors) : self.showErrors($el)
    : self.clearErrors($el)

  if (!prevErrors || errors.toString() !== prevErrors.toString()) {
    e = errors.length
      ? $.Event('invalid.bs.validator', {relatedTarget: $el[0], detail: errors})
      : $.Event('valid.bs.validator', {relatedTarget: $el[0], detail: prevErrors})

    self.$element.trigger(e)
  }

  self.toggleSubmit()

  self.$element.trigger($.Event('validated.bs.validator', {relatedTarget: $el[0]}))
  })
 }


 Validator.prototype.runValidators = function ($el) {
   var errors   = []
   var deferred = $.Deferred()

   $el.data('bs.validator.deferred') && 
   $el.data('bs.validator.deferred').reject()
   $el.data('bs.validator.deferred', deferred)

function getValidatorSpecificError(key) {
  return $el.data(key + '-error')
 }

function getValidityStateError() {
  var validity = $el[0].validity
  return validity.typeMismatch    ? $el.data('type-error')
       : validity.patternMismatch ? $el.data('pattern-error')
       : validity.stepMismatch    ? $el.data('step-error')
       : validity.rangeOverflow   ? $el.data('max-error')
       : validity.rangeUnderflow  ? $el.data('min-error')
       : validity.valueMissing    ? $el.data('required-error')
       :                            null
}

function getGenericError() {
  return $el.data('error')
}

function getErrorMessage(key) {
  return getValidatorSpecificError(key)
      || getValidityStateError()
      || getGenericError()
}

 $.each(this.validators, $.proxy(function (key, validator) {
  var error = null
  if ((getValue($el) || $el.attr('required')) &&
      ($el.data(key) || key == 'native') &&
      (error = validator.call(this, $el))) {
     error = getErrorMessage(key) || error
    !~errors.indexOf(error) && errors.push(error)
  }
 }, this))

if (!errors.length && getValue($el) && $el.data('remote')) {
  this.defer($el, function () {
    var data = {}
    data[$el.attr('name')] = getValue($el)
    $.get($el.data('remote'), data)
      .fail(function (jqXHR, textStatus, error) { errors.push(getErrorMessage('remote') || error) })
      .always(function () { deferred.resolve(errors)})
  })
  } else deferred.resolve(errors)

return deferred.promise()
 }

 Validator.prototype.validate = function () {
var self = this

$.when(this.$inputs.map(function (el) {
  return self.validateInput($(this), false)
})).then(function () {
  self.toggleSubmit()
  self.focusError()
})

return this
 }

 Validator.prototype.focusError = function () {
if (!this.options.focus) return

var $input = this.$element.find(".has-error:first :input")
if ($input.length === 0) return

$('html, body').animate({scrollTop: $input.offset().top - Validator.FOCUS_OFFSET}, 250)
$input.focus()
 }

 Validator.prototype.showErrors = function ($el) {
var method = this.options.html ? 'html' : 'text'
var errors = $el.data('bs.validator.errors')
var $group = $el.closest('.form-group')
var $block = $group.find('.help-block.with-errors')
var $feedback = $group.find('.form-control-feedback')

if (!errors.length) return

errors = $('<ul/>')
  .addClass('list-unstyled')
  .append($.map(errors, function (error) { return $('<li/>')[method](error) 
}))

$block.data('bs.validator.originalContent') === undefined && $block.data('bs.validator.originalContent', $block.html())
$block.empty().append(errors)
$group.addClass('has-error has-danger')

$group.hasClass('has-feedback')
  && $feedback.removeClass(this.options.feedback.success)
  && $feedback.addClass(this.options.feedback.error)
  && $group.removeClass('has-success')
 }

 Validator.prototype.clearErrors = function ($el) {
var $group = $el.closest('.form-group')
var $block = $group.find('.help-block.with-errors')
var $feedback = $group.find('.form-control-feedback')

$block.html($block.data('bs.validator.originalContent'))
$group.removeClass('has-error has-danger has-success')

$group.hasClass('has-feedback')
  && $feedback.removeClass(this.options.feedback.error)
  && $feedback.removeClass(this.options.feedback.success)
  && getValue($el)
  && $feedback.addClass(this.options.feedback.success)
  && $group.addClass('has-success')
 }

 Validator.prototype.hasErrors = function () {
function fieldErrors() {
  return !!($(this).data('bs.validator.errors') || []).length
 }

return !!this.$inputs.filter(fieldErrors).length
 }

 Validator.prototype.isIncomplete = function () {
function fieldIncomplete() {
  var value = getValue($(this))
  return !(typeof value == "string" ? $.trim(value) : value)
  }

 return !!this.$inputs.filter('[required]').filter(fieldIncomplete).length
 }

 Validator.prototype.onSubmit = function (e) {
 this.validate()
 if (this.isIncomplete() || this.hasErrors()) e.preventDefault()
 }

 Validator.prototype.toggleSubmit = function () {
  if (!this.options.disable) return
  this.$btn.toggleClass('disabled', this.isIncomplete() || this.hasErrors())
  }

 Validator.prototype.defer = function ($el, callback) {
callback = $.proxy(callback, this, $el)
if (!this.options.delay) return callback()
window.clearTimeout($el.data('bs.validator.timeout'))
$el.data('bs.validator.timeout', window.setTimeout(callback, this.options.delay))
 }

   Validator.prototype.reset = function () {
   this.$element.find('.form-control-feedback')
  .removeClass(this.options.feedback.error)
  .removeClass(this.options.feedback.success)

 this.$inputs
  .removeData(['bs.validator.errors', 'bs.validator.deferred'])
  .each(function () {
    var $this = $(this)
    var timeout = $this.data('bs.validator.timeout')
    window.clearTimeout(timeout) && $this.removeData('bs.validator.timeout')
  })

 this.$element.find('.help-block.with-errors')
  .each(function () {
    var $this = $(this)
    var originalContent = $this.data('bs.validator.originalContent')

    $this
      .removeData('bs.validator.originalContent')
      .html(originalContent)
  })

  this.$btn.removeClass('disabled')

  this.$element.find('.has-error, .has-danger, .has-success').removeClass('has-error has-danger has-success')

  return this
  }

 Validator.prototype.destroy = function () {
   this.reset()

   this.$element
  .removeAttr('novalidate')
  .removeData('bs.validator')
  .off('.bs.validator')

   this.$inputs
  .off('.bs.validator')

   this.options    = null
   this.validators = null
   this.$element   = null
   this.$btn       = null

   return this
 }

 // VALIDATOR PLUGIN DEFINITION
 // ===========================


 function Plugin(option) {
   return this.each(function () {
  var $this   = $(this)
  var options = $.extend({}, Validator.DEFAULTS, $this.data(), typeof option == 'object' && option)
  var data    = $this.data('bs.validator')

  if (!data && option == 'destroy') return
  if (!data) $this.data('bs.validator', (data = new Validator(this, options)))
  if (typeof option == 'string') data[option]()
   })
   }

 var old = $.fn.validator

 $.fn.validator             = Plugin
 $.fn.validator.Constructor = Validator


 // VALIDATOR NO CONFLICT
 // =====================

 $.fn.validator.noConflict = function () {
   $.fn.validator = old
   return this
   }


   // VALIDATOR DATA-API
   // ==================

   $(window).on('load', function () {
   $('form[data-toggle="validator"]').each(function () {
     var $form = $(this)
     Plugin.call($form, $form.data())
   })
  })

   }(jQuery);

You need to add e.preventDefault(); 您需要添加e.preventDefault(); in the "submit" function to prevent the default form submission behavior. 在“提交”功能中可以防止默认的表单提交行为。

You may also want to try removing "method" and "action" attributes in the HTML part, but I'm not 100 percent sure. 您可能还想尝试删除HTML部分中的“方法”和“动作”属性,但我不确定100%。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM