Yii2: Выводим модальное окно с формой обратной связи и отправляем её 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)