Информация! Пример написан с использованием Bootstrap стилей и скриптов. При необходимость html, css и js Вы можете заменить на свой, это не повлияет на общую логику работы примера.

В конечном результате получи такую форму обратной связи:

Yii Framework, форма обратной связи во сплывающем (модальном) окне с AJAX отправкой данных

И так приступим.

Создадим модель для формы обратной связи в папке /protected/models/, имя класса ContactForm, имя файла модели ContactForm.php, код модели (/protected/models/ContactForm.php):

<?php

class ContactForm extends CFormModel {

    public $name;
    public $email;
    public $subject;
    public $body;
    public $verifyCode;

    public function rules() {
        return array(
            array('name, email, body, verifyCode', 'required'),
            array('email', 'email'),
            array('verifyCode', 'captcha', 'on'=>'new'),
        );
    }

    public function attributeLabels() {
        return array(
            'verifyCode' => 'Капча',
            'name' => 'Имя',
            'email' => 'Э-почта',
            'body' => 'Сообщение',
        );
    }

}

Теперь создадим виджет для всплывающего окна формы обратной связи в папке с виджетами /protected/widgets/, имя класса FBModal, имя файла модели FBModal.php, код виджета (/protected/widgets/FBModal.php):

<?php

class FBModal extends CWidget {
    
    public function init() {
        
        $fBForm = new ContactForm('new');
        $cs = Yii::app()->clientScript;
        $cs->registerScriptFile(Yii::app()->theme->baseUrl . '/js/fbModal.js', CClientScript::POS_END);
        //выводить новую капча при перезагрузки страницы
        Yii::app()->controller->createAction('captcha')->getVerifyCode(true);
        $this->render('webroot.themes.'.Yii::app()->theme->name.'.widgets.FBModal.fBForm', array('fBForm' => $fBForm));
    }        
    
}

Создадим представление (view) для виджета FBModal в папке /themes/themeName/widgets/FBModal/, имя файла fBModal.php, с кодом модального окна (/themes/themeName/widgets/FBModal/fBModal.php):

<!-- Модальное окно формы обратной связи -->
<div class="modal fade" id="fbModal" tabindex="-1" role="dialog" aria-labelledby="fbModalLabel" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
                <h4 class="modal-title" id="myModalLabel">Форма обратной связи</h4>
            </div>
            <?php
            $form = $this->beginWidget('CActiveForm', array(
                'id' => 'uFBForm',
                'action' => '/site/sendFBForm',
                'enableAjaxValidation' => true,
                'enableClientValidation' => true,
                'method' => 'POST',
                'clientOptions' => array(
                    'validateOnSubmit' => true,
                    'validateOnChange' => false,
                    'validateOnType' => false,
                    'afterValidate' => 'js:function(form, data, hasError) {if (!hasError) {fbModalSend();}}',
                    'errorCssClass' => 'has-error',
                ),
                'errorMessageCssClass' => 'small text-danger',
                'htmlOptions' => array('class' => 'contact-form', 'role' => 'form'),
            ));
            ?>
            <div class="modal-body">
                <div class="form-group">
                    <?php
                    echo $form->labelEx($fBForm, 'name');
                    echo $form->textField($fBForm, 'name', array(
                        'class' => 'form-control', 
                        'placeholder' => 'Введите Ваше имя'
                        ));
                    echo $form->error($fBForm, 'name');
                    ?>
                </div>
                <div class="form-group">
                    <?php
                    echo $form->labelEx($fBForm, 'email');
                    echo $form->textField($fBForm, 'email', array(
                        'class' => 'form-control', 
                        'placeholder' => 'Введите E-mail',
                        ));
                    echo $form->error($fBForm, 'email');
                    ?>
                </div>
                <div class="form-group">
                    <?php
                    echo $form->labelEx($fBForm, 'body');
                    echo $form->textArea($fBForm, 'body', array(
                        'rows' => 3, 
                        'cols' => 40, 
                        'class' => 'form-control', 
                        'placeholder' => 'Введите текст сообщения'
                        ));
                    echo $form->error($fBForm, 'body');
                    ?>
                </div>
                <div class="text-right">
                </div>
                <?php if (CCaptcha::checkRequirements()): ?>
                    <div class="form-group">
                        <?php echo $form->labelEx($fBForm, 'verifyCode'); ?>
                        <div class="row">
                            <div class="col-md-4">
                                <?php 
                                    $this->widget('CCaptcha', array(
                                        'buttonLabel' => '<br/>Новый код',
                                        'id' => 'newCode'
                                        )); 
                                ?>
                            </div>
                            <div class="col-md-8">
                                <?php echo $form->textField($fBForm, 'verifyCode', array(
                                    'class' => 'form-control', 
                                    'placeholder' => 'Введите текст указанный на картинке')
                                        );
                                echo $form->error($fBForm, 'verifyCode'); 
                                ?>
                            </div>		
                        </div>
                    </div>
                <?php endif; ?>
            </div>
            <div class="modal-footer">
                <?php
                echo CHtml::htmlButton('Отмена', array(
                    'type' => 'reset', 
                    'class' => 'btn btn-default', 
                    'data-dismiss' => 'modal'
                    ));
                echo CHtml::submitButton('Отправить', array(
                    'class' => 'btn btn-primary'
                    ));
                ?>
            </div>
            <?php
            $this->endWidget();
            ?>
        </div>
    </div>
</div>

<!-- Всплывающее окно с информацией об успешной отправке сообщения -->
<div class="modal fade" id="fbModalOk" tabindex="-1" role="dialog" aria-labelledby="fbModalOkLabel" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
                <h4 class="modal-title" id="myModalLabel">Форма обратной связи</h4>
            </div>
            <div class="modal-body">
                <p>Сообщение успешно отправлено.</p>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-default" data-dismiss="modal">Закрыть</button>
            </div>
        </div>
    </div>
</div>
<!-- Всплывающее окно с информацией об ошибке при отправке сообщения (при необходимости) -->

<!-- ... -->

JavaScript файл для виджета (подключается в классе виджета FBModal, строка 9). Путь к файлу /themes/themeName/js/, имя файла fbModal.js. Скрипт скрывает модальное окно с формой обратной связи после успешной отправки сообщения, очищает поле с текстом сообщения и выводит окно с информацией об успешной отправке сообщения. Код (/themes/themeName/js/fbModal.js):


function fbModalSend() {
    $('#fbModal').modal('hide');
    $('#fbModalOk').modal('show');
    $("#ContactForm_body").val("");
    $("#ContactForm_verifyCode").val("");
    $.ajax({
        url: "/site/captcha?refresh=1",
        dataType: 'json',
        cache: false,
        success: function(data) {
            $('#yw1').attr('src', data['url']);
            $('body').data('captcha.hash', [data['hash1'], data['hash2']]);
            //обновим капчу после успешной отправки
            $('#newCode_button').click();
        }
    });
}

Настройка капчи. Так как у нас в форме обратной связи используется стандартная капча фреймворка, а наш виджет может вызываться в любой части проекта (например в модуле), то внесем настройки капчи в класс предок контроллеров Controller который находиться в папке /protected/components/, файл Controller.php, код (/protected/components/Controller.php):

<?php

class Controller extends CController {

    //...

    public function actions() {
        return array_merge(parent::actions(), array(
            'captcha' => array(
                'class' => 'CCaptchaAction',
                'backColor' => 0xFFFFFF,
                'maxLength' => 4,
                'minLength' => 3,
            //'clickableImage' => true,
            //'width'=> 200,
            //'height'=> 50,
        )));
    }

    //...

}

Отправка формы обратной связи в контролере SiteController (для отправки формы обратной связи Вы можете использовать любой удобный для Вас контроллер). Код (/protected/controllers/SiteController.php):

<?php

class SiteController extends Controller {

    //...

    public function actions() {
            return array_merge(parent::actions(), array(
                'page' => array(
                'class' => 'CViewAction',
            ),
        ));
    }

    //...

    public function actionSendFBForm() {        
        if (Yii::app()->request->isAjaxRequest) {
            $model = new ContactForm('ajax');
            if (isset($_POST['ContactForm'])) {
                $model->attributes = $_POST['ContactForm'];
                if ($model->validate()) {
                    $message = '<p>Э-почта: ' . $model->email . '</p>'
                            . '<p>Имя: ' . $model->name . '</p>'
                            . '<p>Сообщение: ' . $model->body . '</p>';
                    
                    // ... отправка сообщения администратору ...
                    
                    echo CActiveForm::validate($model);
                    Yii::app()->end();
                } else {
                    echo CActiveForm::validate($model);
                }
            }
            Yii::app()->end();
        } else {
            throw new CHttpException(404, 'Указанная запись не найдена');
        }
    }

    //...

}

Вызов формы обратной связи:


<!-- Ссылка(кнопка) вызова модального окна с формой обратной связи -->
<a href="#" data-toggle="modal" data-target="#fbModal">Обратная связь</a>


<?php 
//Подключение виджета с формой обратной связи
$this->widget('application.widgets.FBModal'); 
?>

Все, форма обратной связи во сплывающем окне – готова. Дальнейшие доработки на Ваш вкус)