Yii2: Выводим модальное окно с формой обратной связи и отправляем её Ajax'ом на email
Делаем форму обратной связи в модальном окне, с Ajax-валидацией и отправкой данных формы администратору на email. Некогда мы выводили модальное окно с формой обратной связи на CJuiDialog для Yii 1. Делаем то же теперь в Yii 2. Но теперь используем Bootstrap 3 modal, в целом же вести всплывающую форму отправляющую письмо по ajax, в случае с Yii 2 проще. Это достаточно насущная задача, так как крайне часто требуется на сайте воткнуть кнопку "Оставить онлайн заявку" или "Перезвоните мне".
В работе форму можно посмотреть на сайте нашей школы брейк данса «Inspire».
1) Ставим кнопку, вызывающую модальное окно с формой и само окно (обычно в шаблоне главной страницы)
<p><a class="btn btn-success signup" data-userid="22" >Записаться на занятия</a></p>
<!-- Modal "Записаться на занятия" -->
<div class="modal fade" id="my-modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-body">
...
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
2) Тут же в шаблоне главной, где подключили кнопку (на весь сайт это не нужно распространять), подключаем скрипт:
<?php
$this->registerJsFile(
'scripts/index.js',
['depends'=>'app\assets\AppAsset']
);
?>
3) Его создадим в папке web/scripts.
$(document).ready(function () {
$('.signup').click(function(event){ // нажатие на кнопку - выпадает модальное окно
event.preventDefault();
var url = 'signup';
var clickedbtn = $(this);
//var UserID = clickedbtn.data("userid");
var modalContainer = $('#my-modal');
var modalBody = modalContainer.find('.modal-body');
modalContainer.modal({show:true});
$.ajax({
url: url,
type: "GET",
data: {/*'userid':UserID*/},
success: function (data) {
$('.modal-body').html(data);
modalContainer.modal({show:true});
}
});
});
$(document).on("submit", '.signup-form', function (e) {
e.preventDefault();
var form = $(this);
$.ajax({
url: "submitsignup",
type: "POST",
data: form.serialize(),
success: function (result) {
console.log(result);
var modalContainer = $('#my-modal');
var modalBody = modalContainer.find('.modal-body');
var insidemodalBody = modalContainer.find('.gb-user-form');
if (result == 'true') {
insidemodalBody.html(result).hide(); //
//$('#my-modal').modal('hide');
$('#success').html("<div class='alert alert-success'>");
$('#success > .alert-success').append("<strong>Спасибо! Ваше сообщение отправлено.</strong>");
$('#success > .alert-success').append('</div>');
setTimeout(function() { // скрываем modal через 4 секунды
$("#my-modal").modal('hide');
}, 4000);
}
else {
modalBody.html(result).hide().fadeIn();
}
}
});
});
});
Здесь 2 события. Первое выполняется по нажатию кнопки с классом .signup и обращается к URL = "signup", который пропишем дальше в rules у urlManager. Сразу пропишем и для второго события.
'signup'=>'site/signup', 'submitsignup'=>'site/submitsignup',
Вторая функция обрабатывает отправку формы. И если получен ответ true, то выводит сообщение об успешной отправке письма и закрывает модальное окно через 4 секунды (если посетитель сам не закрыл его раньше). Если будет получен не true, а что-то другое, то это покажется в модальном окне, тут делается скрытие и обновление его .hide().fadeIn().
4) Едем дальше. В контроллере SiteController методы signup и submitsignup
// Всплывшее модальное окно заполняем представлением signup.php формы с полями
public function actionSignup()
{
$model = new \app\models\SignupForm();
//$model->id =$userid;
return $this->renderPartial('signup', [
'model' => $model,
]);
}
// По нажатию в модальном окне на Отправить - форма отправляется администратору на почту
public function actionSubmitsignup()
{
$model = new \app\models\SignupForm();
$model->load(Yii::$app->request->post());
if($model->load(Yii::$app->request->post()) && $model->contact(Yii::$app->params['adminEmail'])) {
//save the password
$success=true;
return json_encode($success);
}
else
{
return $this->renderPartial('signup', [
'model' => $model,
]);
}
}
Как раз первый заполняет в модельное окно форму через renderPartial. Второй метод submitsignup похож на contact - он таким же образом эту форму отправляет на email.
5) Создадим модель SignupForm.php (очень похожую на ContactForm)
<?php
namespace app\models;
use Yii;
use yii\base\Model;
use yii\helpers\Security;
class SignupForm extends Model
{
public $name;
public $phone;
public $email;
/**
* Здесь мы указываем правила валидации - они могут быть как стандартными, так и кастомными
*/
public function rules()
{
return [
['name', 'required'],
//[['phone','email'], 'safe'],
[['email'], 'email'],
[['phone', 'email'], 'validatePhoneEmailEmpty', 'skipOnEmpty'=> false],
];
}
public function attributeLabels()
{
return [
'name' => 'Ваше имя',
'email' => 'Email',
'phone' => 'Телефон',
];
}
/* Кастомная функция для проверки, что хотя бы одно из полей email или phone посетитель заполнил */
public function validatePhoneEmailEmpty()
{
if(empty($this->phone) && empty($this->email))
{
$errorMsg= 'Укажите ваш email или телефон';
$this->addError('phone',$errorMsg);
$this->addError('email',$errorMsg);
}
if(!empty($this->phone) && (strlen($this->phone)<7))
{
$errorMsg= 'Слишком мало цифр в номере телефона';
$this->addError('phone',$errorMsg);
}
}
/**
* Аналог ContactForm
*/
public function contact($email)
{
if ($this->validate()) {
Yii::$app->mailer->compose()
->setTo($email)
->setFrom(['youremail@adress.ru' => $this->name])
->setSubject('Заявка на занятия по брейку от '.$this->name)
->setTextBody($this->email."\n Телефон: ".$this->phone)
->send();
return true;
} else {
return false;
}
}
}
6) И само представление формы
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
/**
* @var yii\web\View $this
* @var app\models\gbUser $model
* @var yii\widgets\ActiveForm $form
*/
?>
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
<div id="success"> </div> <!-- For success message -->
<div class="gb-user-form">
<?php $form = ActiveForm::begin(['options' => ['class' => 'signup-form']]); ?>
<?= $form->field($model, 'name')->textInput(['maxlength' => 255], ['class' => 'input-modal']) ?>
<?= $form->field($model, 'phone')->textInput(['maxlength' => 255], ['class' => 'input-modal']) ?>
<?= $form->field($model, 'email')->textInput(['maxlength' => 255], ['class' => 'input-modal']) ?>
<div class="form-group text-right">
<?= Html::submitButton('Отправить', ['class' => 'btn btn-success btn-update-password']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
N.B. Обратите внимание, что письма по-умолчанию отправляются swiftmailer через функцию mail(). Посмотрите в настройках конфига, чтобы на рабочем проекте на сервере был выключен параметр useFileTransport. Это задаётся в настройках компонента mailer (либо закомментруйте строку, либо явно укажите 'useFileTransport' => false,)
'mailer' => [
'class' => 'yii\swiftmailer\Mailer',
// send all mails to a file by default. You have to set
// 'useFileTransport' to false and configure a transport
// for the mailer to send real emails.
//'useFileTransport' => true,
],
Если этого не сделать, то все письма будут складываться и скапливаться в runtime/mail, а не отправляться адресату:

Вот и всё. У вас должно получиться модальное окно, появляющееся по нажатию на кнопку. В окне форма, у которой работает ajax валидация и нажав "Отправить" эти данные отправляются администратору без перезагрузки страницы!
P.S. Если кому-то будет интересно, вот как без фреймворков сразу на скриптах - Модальное окно Bootstrap 3 с формой, отправляющей email по Ajax (пригодится, если будете клепать лендинг-страницы без движков).
Сильно помогло:
almix
Разработчик Loco, автор статей по веб-разработке на Yii, CodeIgniter, MODx и прочих инструментах. Создатель Team Sense.
Вы можете почитать все статьи от almix'а.
- 14 Разработка приложения на Yii. Урок 14: Выводим список категорий как новый виджет на сайте (29.04.2015)
- 13 Разработка приложения на Yii. Урок 13: Внедряем категории для статей. (29.04.2015)
- 12 Разработка приложения на Yii. Урок 12: Профилирование приложения, включаем кеширование. (20.01.2015)
- 11 Yiico. Видеокурс по разработке сайта на Yii. Урок 11: Отладка приложения, включаем журналирование. (20.01.2015)
- 10 Yiico. Видеокурс по разработке сайта на Yii. Урок 10: Если ваше приложение находится не в корневой папке, а во вложенной. (19.10.2014)
- 9 Разработка сайта на Yii с нуля. Урок 9. Выборка статей определённого автора. (13.08.2014)
- 8 Разработка сайта на Yii с нуля. Урок 8. Вызов в моделях функции, общей для них. Как избегать дублирования кода? (25.07.2014)
- 7 Разработка сайта на Yii с нуля. Урок 7. Изменение количества выводимых записей на странице в CGridView. Включаем сессии Yii. (04.09.2013)
- 6 Разработка сайта на Yii с нуля. Урок 6. Автоматич. отправка оповещений об одобренных комментариях на email автора комментария (11.08.2013)
- 5 Разработка сайта на Yii с нуля. Урок 5. Переименовываем blog в yiico. Изменяем "Home" в breadcrumbs. Включаем Gzip-сжатие. (09.08.2013)
- 4 Курс по Yii с нуля. Урок 4. Дорабатываем простую работу с пользователями: хранение пароля при редактировании пользователя. (13.04.2013)
- 3 Курс по Yii с нуля. Урок 3. Создаём новых пользователей. Организуем простую систему авторизации. Аутентификация, пароли, соли. (20.07.2014)
- 2 Yii + Git (github) на Mac. (24.03.2013)
- 2 Курс по Yii с нуля. Урок 2. Переносим и настраиваем Yii и проект нашего сайта на рабочем сервере. Избавляемся от index.php в url (09.07.2014)
- 1 Курс по Yii с нуля. Урок 1. Устанавливаем Yii на локальном компьютере. Заводим проект будущего сайта. (10.03.2013)
- 0 Composer – пакетный менеджер PHP. Что и как? (22.07.2014)
- 0 MySQL: проверить содержится ли значение в поле столбца (в столбце хранится строка значений через запятую) (22.05.2014)
- 0 Yii: Статичные страницы (создание, редактирование, удаление) (28.04.2014)
- 0 Yii: Расширение ECKEditor = Связка ckeditor + kcfinder (визуальный редактор с бесплатным файловым менеджером) (28.04.2014)
- 0 Yii: Bootstrap tabs, делаем активной вкладку на которую выполняется переход по ссылке (20.03.2014)
- 0 Yii: Доступ к атрибуту модели из файла шаблона (Вызов в шаблоне какого-либо атрибута модели). (17.02.2014)
- 0 Yii: Множественный автокомплит с помощью CJuiAutoComplete (автокомплит нескольких значений в одно поле) (07.02.2014)
- 0 Yii: Фотогалерея через поведение (доработка расширения imagesgallerymanager) (08.03.2016)
- 0 Yii: Установка и настройка Yii-app заготовки приложения от Crisu83 (09.03.2014)
- 0 Twitter Bootstrap Carousel Crossfade (09.09.2013)


