首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

Yii2 Bootstrap Modal 彈窗完整應用:AJAX 載入、表單提交與 GridView 整合

     編輯:PHP 相關知識

Yii2 彈窗元件實戰指南:從基礎用法到進階整合

Yii2 內建 yii\bootstrap\Modal (或 yii\bootstrap5\Modal) 封裝了 Bootstrap Modal,支援 AJAX 遠端載入內容、表單驗證提交與 GridView 列表操作。本文完整示範建立、載入、提交、關閉的生命週期處理。

基礎結構:按鈕觸發 + Modal 容器

<?php
use yii\helpers\Html;
use yii\bootstrap\Modal;
use yii\helpers\Url;

// 1. 觸發按鈕
echo Html::a('建立新項目', '#', [
    'id'           => 'create-btn',
    'class'        => 'btn btn-success',
    'data-toggle'  => 'modal',
    'data-target'  => '#create-modal',
    'data-url'     => Url::toRoute(['create']), // 可選:儲存 URL 供 JS 使用
]);

// 2. Modal 容器 (放在視圖檔案底部)
Modal::begin([
    'id'           => 'create-modal',
    'title'        => '<h4>建立新項目</h4>',
    'headerOptions' => ['class' => 'bg-primary text-white'],
    'footer'       => Html::a('關閉', '#', ['class' => 'btn btn-secondary', 'data-dismiss' => 'modal']),
    'size'         => Modal::SIZE_LARGE, // 或 SIZE_SMALL, 預設
    'clientOptions' => [
        'backdrop' => 'static', // 點擊背景不關閉
        'keyboard' => false,    // ESC 不關閉
    ],
]);
Modal::end();

AJAX 載入表單內容

<?php
// 在 Modal::begin() 之後、Modal::end() 之前註冊 JS
$requestUrl = Url::toRoute(['create']);
$js = <<載入中...
'); $.get('$requestUrl', function (html) { \$body.html(html); \$body.data('loaded', true); // 重新綁定表單提交事件 (關鍵:動態載入的表單需重新綁定) \$body.find('form').on('submit', function (e) { e.preventDefault(); submitModalForm($(this), \$modal); }); }).fail(function () { \$body.html('
載入失敗,請稍後再試
'); }); }); // 監聽 modal 隱藏事件,清理狀態 (可選) $('#create-modal').on('hidden.bs.modal', function () { $(this).find('.modal-body').html('').removeData('loaded'); }); JS; $this->registerJs($js, \yii\web\View::POS_READY);

表單 AJAX 提交處理

<?php
// 繼續在同一個視圖檔案註冊提交函式
$js = <<' + messages[0] + '
'); }); } else if (response.message) { alert(response.message); } } }, error: function () { alert('請求失敗,請檢查網路連線'); }, complete: function () { \$submitBtn.prop('disabled', false).html(originalText); } }); } JS; $this->registerJs($js, \yii\web\View::POS_READY);

控制器動作實作

<?php
// SiteController.php
public function actionCreate()
{
    $model = new Project(); // ActiveRecord 模型
    
    if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
        Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
        
        if ($model->validate() && $model->save()) {
            return ['success' => true, 'id' => $model->id];
        } else {
            return ['success' => false, 'errors' => $model->getErrors()];
        }
    }
    
    // 非 AJAX 或首次載入:渲染部分視圖 (無 layout)
    return $this->renderAjax('_form', ['model' => $model]);
}

部分視圖 _form.php

<?php
use yii\widgets\ActiveForm;
use yii\helpers\Html;

$form = ActiveForm::begin([
    'id' => 'project-form',
    'enableAjaxValidation' => true, // 可選:支援欄位級即時驗證
    'validationUrl' => Url::toRoute(['validate']), // 需實作 validate action
]);
?>
    <div class="modal-body">
        <?= $form->field($model, 'name')->textInput(['maxlength' => true]) ?>
        <?= $form->field($model, 'description')->textarea(['rows' => 4]) ?>
        <?= $form->field($model, 'status')->dropDownList([1 => '啟用', 0 => '停用']) ?>
    </div>
    <div class="modal-footer">
        <?= Html::submitButton('儲存', ['class' => 'btn btn-primary']) ?>
        <?= Html::a('取消', '#', ['class' => 'btn btn-secondary', 'data-dismiss' => 'modal']) ?>
    </div>
<?php ActiveForm::end(); ?>

進階:GridView 整合 (編輯/刪除彈窗)

<?php
use yii\grid\GridView;
use yii\helpers\Html;

echo GridView::widget([
    'dataProvider' => $dataProvider,
    'filterModel'  => $searchModel,
    'id'           => 'gridview-pjax', // 對應 Pjax 容器 ID
    'columns' => [
        'id',
        'name',
        'status:boolean',
        [
            'class' => 'yii\grid\ActionColumn',
            'template' => '{view} {update} {delete}',
            'buttons' => [
                'update' => function ($url, $model, $key) {
                    return Html::a('', '#', [
                        'class' => 'btn-update',
                        'data-url' => $url,
                        'data-id' => $key,
                        'title' => '編輯',
                    ]);
                },
                'delete' => function ($url, $model, $key) {
                    return Html::a('', '#', [
                        'class' => 'btn-delete',
                        'data-url' => $url,
                        'data-id' => $key,
                        'title' => '刪除',
                        'data-confirm' => '確定刪除?',
                    ]);
                },
            ],
        ],
    ],
]);

JS 處理 GridView 按鈕

<?php
$js = <<編輯項目');
    \$modal.modal('show');
    
    // 載入表單 (同上 AJAX 邏輯)
    // ...
});

// 刪除按鈕 (AJAX 刪除)
$(document).on('click', '.btn-delete', function (e) {
    e.preventDefault();
    if (!confirm($(this).data('confirm'))) return;
    
    var \$btn = $(this);
    var url = \$btn.data('url');
    
    $.post(url, function (response) {
        if (response.success) {
            $.pjax.reload({container: '#gridview-pjax'});
        } else {
            alert(response.message || '刪除失敗');
        }
    }, 'json');
});
JS;
$this->registerJs($js, \yii\web\View::POS_READY);

關鍵注意事項

  1. ID 唯一性:頁面只能有一個相同 ID 的 Modal,複用時動態修改標題與內容。
  2. 事件重新綁定:AJAX 載入的表單必須在 success 回呼中重新綁定 submit 事件。
  3. Pjax 容器:GridView 外層包裹 Pjax::begin(['id' => 'gridview-pjax']) 實現無刷新刷新。
  4. 驗證錯誤渲染:AJAX 驗證回傳 errors 陣列,JS 需對應欄位顯示 is-invalid 樣式。
  5. Bootstrap 版本:Yii2 使用 Bootstrap 4/5,確認 data-bs-* (BS5) 或 data-* (BS4) 屬性前綴。
  1. 上一篇文章:
  2. 下一篇文章:
欄目導航
Copyright © 程式碼之家 All Rights Reserved