Создаем контактную форму с использованием Bootstrap, PHP и AJAX

В этой статье я опишу создание и отправку формы AJAX. После этого мы сможем рассмотреть реализацию анимации с помощью animate.css, валидации данных с помощью JavaScript.

На момент написания данной статьи Bootstrap 3.3.5 является актуальной версией фреймворка. Для этой статьи мы используем сборку Bootstrap по умолчанию (с 12 столбцами). Когда вы будете выполнять задания этой статьи, убедитесь, что используете последние сниппеты и структуру кода, описанные в документации Bootstrap.

Структура файлов и папок

Мы создадим корневой каталог и добавим в него следующие файлы и папки:

Bootstrap-Form:

Структура файлов и папок

Нам нужно будет подключить некоторые front-end библиотеки:

  • Bootstrap;
  • jQuery.

С учетом этих библиотек структура файлов будет выглядеть следующим образом:

Bootstrap-Form:

Структура файлов и папок - 2

Создание формы

Откройте файл index.html и скопируйте в него следующую базовую структуру AJAX формы обратной связи:

<!DOCTYPE html>
<html>
<head>
    <title>Contact form using Bootstrap 3.3.4</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <meta charset="utf-8">
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <link rel="stylesheet" href="css/bootstrap.css">
<link rel="stylesheet" href="css/animate.css">

</head>
<body>"
<div class="row">
<div class="col-sm-6 col-sm-offset-3">
    <h3>Send me a message</h3>
    <form role="form" id="contactForm">

    </form>
</div>
</div>
</body>
<script  src="js/jquery-1.11.2.min.js"></script>
<script src="js/form-scripts.js"></script>
</html>

Это базовый шаблон HTML, в который мы будем добавлять содержимое формы. Мы подключили все необходимые файлы CSS и JavaScript. Заметьте, что для этого конкретного примера нам не нужен bootstrap.js.

Мы включили мета-тег viewport для медиа-запросов в рамках Bootstrap. JavaScript был помещен в нижней части файла, чтобы в первую очередь обрабатывался основной код.

В теге body мы включили div с классом col-sm-6 col-sm-offset-3. Это означает, что в пределах окна просмотра sm (маленького) и поверх него мы хотим отобразить столбец шириной 50% (максимальное количество столбцов 12). Класс col-sm-offset-3 задает отступ слева на 25%.

Таким образом, создается макет, который занимает половину доступного пространства и отцентрирован по горизонтали. После этого мы включили h3, и дальше идет основа формы. Убедитесь в том, что вы применили к форме идентификатор, чтобы позже прикрепить к ней событие для отправки формы AJAX JQuery:

Создание формы

Без борьбы не бывает победы

Дальше нужно вставить следующий код внутри тегов <form></form>:

<div class="row">
            <div class="form-group col-sm-6">
                <label for="name" class="h4">Name</label>
                <input type="text" class="form-control" id="name" placeholder="Enter name" required>
            </div>
            <div class="form-group col-sm-6">
                <label for="email" class="h4">Email</label>
                <input type="email" class="form-control" id="email" placeholder="Enter email" required>
            </div>
        </div>
        <div class="form-group">
            <label for="message" class="h4 ">Message</label>
            <textarea id="message" class="form-control" rows="5" placeholder="Enter your message" required></textarea>
        </div>
        <button type="submit" id="form-submit" class="btn btn-success btn-lg pull-right ">Submit</button>
<div id="msgSubmit" class="h3 text-center hidden">Message Submitted!</div>

Это все поля ввода и кнопки, с которыми будет взаимодействовать пользователь. Первоначальный div с присвоенным классом row - это классический синтаксис Bootstrap, представляющий собой горизонтальную группировку элементов col. Столбцы в пределах Bootstrap создают отступы или пробелы. Удаляя их, можно добиться, чтобы строка равномерно вписывалась в контейнер.

Мы создали два столбца с классом col-sm-6 (50%), который будем использовать, чтобы отделить верхнюю часть формы. В пределах первого столбца col-sm-6 мы создали label и поля для имени и электронной почты. Каждый из них содержит label с соответствующим атрибутом for, поэтому метка связана с соответствующим полем.

Каждый из этих столбцов включает в себя form-group, который семантически группирует метки, создавая небольшой отступ снизу:

Без борьбы не бывает победы

Типографика

Bootstrap позволяет использовать классы для H1-H6. Они помогают задать стили встроенных элементов без добавления дополнительных полей или создания блоков элементов super AJAX contact form. Мы использовали класс для H4, чтобы задать стиль label и сделать их большими.

Класс form-control применяется для каждого элемента ввода, чтобы он занимал всю ширину контейнера (ширина 100%). Этот класс также добавляет различные стили, которые позволяют создать легко читаемый элемент формы (большой размер, четкие края и т.д.).

После этих столбцов мы включаем тело сообщения. Мы оборачиваем его в form-group и применяем те же стили, что и для меток и для текстовых полей.

Призыв к действию

Создадим submit button. Bootstrap содержит классы для различных кнопок и их состояний. Мы решили использовать кнопку “success” (btn-success), которая, по умолчанию, является зеленой.

Также нужно применить базовый класс btn, чтобы сбросить основные параметры кнопки (рамка, отступ, выравнивание текста, размер шрифта). Мы применили класс btn-lg, который создает большую кнопку, а затем класс pull-right, который задает обтекание кнопки слева.

После кнопки мы включили div с идентификатором #msgSubmit и применили следующие классы: "h3 text-center hidden". Класс h3 помогает создать больший заголовок, text-center устанавливает выравнивание текста по центру, а hidden - задает display: none и visible: hidden:

Призыв к действию

Добавление функционала отправки данных

Мы создали базовую Bootstrap JQuery AJAX form, но она еще ничего не делает. Наш следующий шаг - создать функцию, которая принимает вводимые Пользователями данные и отправляет их асинхронно в PHP.

Откройте файл scripts.js и скопируйте в него следующий код:

$("#contactForm").submit(function(event){
    // отменяет отправку данных формы
    event.preventDefault();
    submitForm();
});

Этот фрагмент кода JQuery, который прослушивает функции отправки данных #contactForm (как указано ранее). Перед этой функцией мы обрабатываем переменную event, которая хранит действие отправки данных формы для функции.

event.preventDeafult() останавливает отправку данных формы при обновлении страницы без выбора действия в форме. И в конце этот код запрашивает функцию submitForm();:

submitForm();

Далее мы создаем функцию submitForm(); следующим образом:

function submitForm(){
    // Инициируем переменную с содержимым формы
    var name = $("#name").val();
    var email = $("#email").val();
    var message = $("#message").val();

    $.ajax({
        type: "POST",
        url: "php/form-process.php",
        data: "name=" + name + "&email=" + email + "&message=" + message,
        success : function(text){
            if (text == "success"){
                formSuccess();
            }
        }
    });
}
function formSuccess(){
    $( "#msgSubmit" ).removeClass( "hidden" );
}

Три инициированные переменные захватывают значения каждого из полей ввода формы и передают их переменной JavaScript для использования в дальнейшем.

Мы инициируем объект AJAX внутри JQuery и устанавливаем параметры для post, адрес размещения файла PHP, данные, которые мы хотим отправить, и функцию обратного вызова. Данные включают в себя все три переменные с соответствующим id. Функция обратного вызова вызывается, когда объект AJAX успешно принял информацию от скрипта PHP. Функция захватывает возвращенный текст и проверяет, равен ли он строке “success”. Если да, то запускается финальная функция formSuccess.

Она удаляет скрытый класс из DIV #msgSubmit, который мы применили ранее, выводя таким образом текст.

Подключение к функции PHP Mail

Теперь нужно написать скрипт, который будет получать данные из формы AJAX, и отправлять контент через функцию PHP Mail. Откройте файл process.php и добавьте в него следующий код:

<?php
$name = $_POST["name"];
$email = $_POST["email"];
$message = $_POST["message"];

$EmailTo = "emailaddress@test.com";
$Subject = "New Message Received";

// готовим тело электронного письма
$Body .= "Name: ";
$Body .= $name;
$Body .= "n";

$Body .= "Email: ";
$Body .= $email;
$Body .= "n";

$Body .= "Message: ";
$Body .= $message;
$Body .= "n";

// отправляем электронную почту
$success = mail($EmailTo, $Subject, $Body, "From:".$email);

// перенаправляем на страницу сообщения об успешной отправке данных формы
if ($success){
   echo "success";
}else{
    echo "invalid";
}

?>

Нам необходимо сохранить переменные, которые мы хотим использовать. Из почтовой функции можно получить три входных переменных и присвоить им те же имена в PHP. Переменная $EmailTo является адресом электронной почты, которую можно задать в скрипте. $Subject - это строка, описывающая тему электронного письма.

Тело письма создается произвольно с добавлением трех созданных переменных. Сначала мы задаем текст описания, например, "Name:", затем идет переменная, а затем перенос на новую строку (/n). Те же действия мы повторяем, связывая все данные с переменной $body.

Чтобы отправить электронное письмо, мы присоединяем его к почтовой функции. Присвоив значение переменной $success, мы задаем адрес электронной почты, на который будет отправлено письмо, тему письма, тело и адрес электронной почты отправителя.

Чтобы начать процесс отправки электронной почте, нужно вызвать его в операторе if. Таким образом можно проверить, были ли данные формы успешно предоставлены или нет. Если функция Mail возвращает “true”, скрипт возвращает “success”, если функция выдает ошибку, возвращается “invalid”.

Этот результат будет возвращаться объекту AJAX, и обрабатываться на стороне клиента. Преимущества AJAX заключается в том, что все это делается в асинхронном режиме на стороне клиента. Это позволяет пользователю продолжать взаимодействовать с сайтом во время отправки данных AJAX form:

Подключение к функции PHP Mail

Наводим блеск

Теперь мы сконцентрируемся на обеспечении обратной связи с пользователем с помощью различных дополнительных функций, которые можно включить. В частности, мы рассмотрим обратную связь формы с помощью обработки ошибок, как на стороне клиента, так и на стороне сервера.

Также для валидации формы мы используем некоторые инструменты:

  • Animate.css;
  • Bootstrap Validator.

Добавьте их в проект, как мы ранее делали с Bootstrap и JQuery. Эти инструменты помогут обеспечить обратную связь с пользователем после того, как он отправил данные.

Структура проекта теперь должна выглядеть следующим образом:

Наводим блеск

Валидация формы

Давайте начнем с установки валидатора после ввода данных формы обратной связи AJAX PHP. Перейдите в файл scripts.js и отредактируйте первый фрагмент кода, который вызывает функцию SubmitForm() после того, как данные формы отправлены.
Его нужно изменить следующим образом:

$("#contactForm").validator().on("submit", function (event) {
    if (event.isDefaultPrevented()) {
        // обработка ошибки формы...
    } else {
        // все в порядке!
        event.preventDefault();
        submitForm();
    }
});

Этот новый фрагмент кода проверяет, нашел ли Bootstrap Validator проблемы и остановил ли работу кода. Если нет, мы продолжаем выполнение действий в стандартном режиме. Нам все еще нужно исключить действие по умолчанию (перезагрузку страницы без заполнения формы) из сценария представления данных формы.

Теперь, если мы нажмем кнопку отправки данных формы, не заполнив все поля, пустые будут выделяться красным цветом:

Валидация формы

В процессе добавления валидации мы заблокировали родную валидацию HTML5. Можно добавить в валидацию дополнительный контекст, включив сообщения об ошибках. Bootstrap Validator имеет удобную функцию, позволяющую отобразить сообщения об ошибке по каждому из полей. Чтобы добавить их, нужно дополнить разметку HTML.

Внутри каждой form-group под полем ввода данных нужно разместить следующий HTML-код:

<div class="help-block with-errors"></div>

В качестве примера ниже приведен дополнительный div, добавляемый полям имени и адреса электронной почты:

<div class="row">
    <div class="form-group col-sm-6">
        <label for="name" class="h4">Name</label>
        <input type="text" class="form-control" id="name" placeholder="Enter name" required>
        <div class="help-block with-errors"></div>
    </div>
    <div class="form-group col-sm-6">
        <label for="email" class="h4">Email</label>
        <input type="email" class="form-control" id="email" placeholder="Enter email" required>
        <div class="help-block with-errors"></div>
    </div>
</div>

Теперь при повторной отправке данных AJAX JQuery формы будет выводиться сообщение об ошибке, если поля формы не были заполнены: “Please fill in this field.”. Добавив data-атрибут для вводимых данных под названием “data-error”, можно включить пользовательское сообщение об ошибке.

Например:

<input type="input" data-error="Новое сообщение об ошибке">
Валидация формы - 2

Добавление анимации обратной связи

Мы добавили функционал для индикации незаполненных полей формы. Но было бы неплохо добавить в форму дополнительную анимацию и несколько сообщений, которые дадут пользователю знать, что происходит. В настоящее время при успешной отправке данных формы появляется сообщение "Message Submitted!", но как насчет ошибок?

Чтобы задействовать существующий код, мы изменим существующее сообщение об успешной отправке данных. Первым делом удалим текст "Message Submitted!" из HTML-разметки и оставим пустой div:

<div id="msgSubmit" class="h3 text-center hidden"></div>

Теперь нужно создать новую функцию для обработки статуса сообщения. Добавьте эту функцию в нижнюю часть файла scripts.js:

function submitMSG(valid, msg){
        var msgClasses;
    if(valid){
        msgClasses = "h3 text-center tada animated text-success";
    } else {
        msgClasses = "h3 text-center text-danger";
    }
    $("#msgSubmit").removeClass().addClass(msgClasses).text(msg);
}

Эта функция принимает два аргумента. valid будет логической переменной: если ее значение true, будет выводиться сообщение об успешной отправке данных. Если false, будет выводиться сообщение об ошибке. msg - это сообщение, которое мы будем выводить на экран в блоке div.

Данная функция проверяет, имеем ли мы дело с сообщением об успешной отправке данных или с сообщением об ошибке. Это делается через проверку значения переменной valid. В любом случае она устанавливает переменную с соответствующими классами CSS (нам необходимо повторно включить h3 и text-center, так как мы удалим их).

Примечание: Для класса сообщения об успешной отправке данных мы используем некоторые классы animate.css. При успешной отправке данных AJAX JQuery contact form будет проигрываться анимация tada.

Наконец, функция удаляет все классы из #msgSubmit (чтобы избежать пересечения классов), а затем устанавливает приоритетные классы и добавляет текст сообщения в div.

Внутри инициализации валидатора в начале этого раздела мы обновляем код, чтобы добавить вызов следующей функции внутри оператора if, когда он дает значение true:

submitMSG(false, "Did you fill in the form properly?");

Теперь, если вы не заполнили все поля, будет выводиться сообщение об ошибке “Did you fill in the form properly?"

Последний шаг для этой новой функции submitMSG - вызвать ее, когда данные формы отправлены успешно. Обновите функцию formSuccess() следующим образом:

$("#contactForm")[0].reset();
submitMSG(true, "Message Submitted!")

Мы хотим сбросить форму и очистить значения, когда вызываем функцию submitMSG, как указано выше с сообщением об успешной отправке данных. Теперь при успешной отправке данных формы должно отображаться соответствующее сообщение с анимацией animate.css tada:

Добавление анимации обратной связи

Встряхнемся

Давайте добавим ко всей форме анимацию ошибки, универсальная анимация “тряски” должна подойти!

Создайте сразу после функции formSuccess() новую и назовите ее formError():

function formError(){
    $("#contactForm").removeClass().addClass('shake animated').one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function(){
        $(this).removeClass();
    });
}

Эта функция использует подход, описанный на демонстрационной странице animate.css, который позволяет добавить анимацию к элементу, а затем повторно вызывать ее снова.

Анимация CSS имеет неприятную особенность: отсутствие возможности повторного проигрывания, даже если удалить и повторно добавить класс. Эта функция помогает сбросить классы конца анимации, что позволяет повторно добавить их. Когда пользователь нажимает кнопку «Отправить», не заполнив все поля AJAX формы обратной связи, мы проигрываем анимацию shake. И если он снова не заполнит все поля, нужно снова проиграть эту анимацию.

Можно вызвать эту функцию formError() выше функции submitMSG(), которую мы создали для сообщения об ошибке. Например, так:

formError();
submitMSG(false, "Did you fill in the form properly?");

Теперь, когда пользователь попытается отправить данные формы, не заполнив все поля, она будет трястись, чтобы он понял, что что-то не так.

Больше валидации

Валидация на стороне клиента - это хорошо, но любой пользователь может отключить ее и отправить форму с пустыми полями, отредактировав код в браузере. Необходимо создать сервис валидации на стороне сервера.

Нам нужно открыть файл process.php и внести в него необходимые изменения, чтобы обеспечить проверку заполнения всех полей. Мы создадим переменную $errorMSG, с помощью которой будем перехватывать сообщения об ошибках, а затем включим дополнительную проверку $_POST:

<?php
$errorMSG = "";

// ИМЯ
if (empty($_POST["name"])) {
    $errorMSG = "Name is required ";
} else {
    $name = $_POST["name"];
}

// E-MAIL
if (empty($_POST["email"])) {
    $errorMSG .= "Email is required ";
} else {
    $email = $_POST["email"];
}

// СООБЩЕНИЕ
if (empty($_POST["message"])) {
    $errorMSG .= "Message is required ";
} else {
    $message = $_POST["message"];
}

?>

Этот PHP-код проверяет, существуют ли пустые поля AJAX form, перед тем как установить их данные в качестве соответствующих переменных (заменяет существующие заданные в коде переменные из $_POST). Если поля пусты, мы задаем общее сообщение для отправки обратно клиенту.

В ответ на исходный вызов AJAX нам нужно послать сообщение об ошибке, которое будет отображаться в браузере. Для этого отредактируйте оператор if, который мы создали ранее в нижней части кода PHP:

<?php
// перенаправление на страницу с сообщением об успешной отправке данных
if ($success && $errorMSG == ""){
   echo "success";
}else{
    if($errorMSG == ""){
        echo "Something went wrong :(";
    } else {
        echo $errorMSG;
    }
}

?>

Через оператор if мы проверяем, является ли переменная $errorMSG пустой (""), а также статус встроенной функции Mail, которую мы использовали для переменной $success. В условии else мы включили дополнительную проверку, является ли ошибка результатом сбоя $success. Если да, то отправляем обратно сообщение “Something went wrong :“. Иначе выводим сообщение, которое было скомпилировано, когда мы производили проверку пустых полей.

И последний этап - нужно принять новое сообщение в AJAX и вывести его в форме. Нам нужно обновить объект AJAX в файле scripts.js следующим образом:

$.ajax({
      type: "POST",
      url: "php/form-process.php",
      data: "name=" + name + "&email=" + email + "&message=" + message,
      success : function(text){
          if (text == "success"){
              formSuccess();
          } else {
              formError();
              submitMSG(false,text);
          }
      }
  });

Мы только что обновили условия else, которое проверяет соответствие text == success. В else мы вызываем функцию formError(), которая применяет анимацию "тряски" и запрашиваем у функции submitMSG() текст, возвращенный из PHP.

Заключение

Зайдите на Github, чтобы посмотреть весь код целиком. Теперь форма обратной связи AJAX PHP предоставляет пользователю информацию о том, какие из полей он не заполнил. Мы выводим контекстные сообщения, основанные на статусе и возвращаемом от PHP сообщении. А также реализовали дополнительный уровень проверки на стороне сервера для тех пользователей, которые пытаются обойти front-end валидацию.