This is an old revision of the document!
Yii 2 Modal Window
Ad Hoc Modal
Create a button to call modal:
<?= Html::button(Yii::t('app', 'Open'), [ // ... 'data' => [ 'toggle' => 'modal', 'target' => '#modalPopup', ], ]) ?>
Create a modal using widget:
yii\bootstrap\Modal::begin([ 'id' => '#modalPopup', //... ]); // Some modal content here yii\bootstrap\Modal::end();
Modal with Image
<?php //------------------------ // Image //------------------------ $itemImage = (!empty($model->image_file) ? Yii::$app->homeUrl . 'img/data/' . Yii::$app->controller->id . "/{$model->image_file}" : '' ); //------------------------ // Image Thumbnail //------------------------ if(!empty($itemImage)) { echo "<img class='img-thumbnail' src='{$itemImage}' alt='Item Image'>"; } else { echo "<img class='img-thumbnail' src='data:image/png;base64," . base64_encode(\app\models\Tool::generateEmptyPng()) . "'/>"; } echo Html::a('<i class="fa fa-plus" aria-hidden="true"></i> ' . Yii::t('app', 'Add Image'), ['upload-image', 'id' => $model->id], ['class' => 'btn btn-default'] ); //------------------------ // Modal to view image //------------------------ yii\bootstrap\Modal::begin([ 'header' => '<h4>Item Image</h4>', 'size' => yii\bootstrap\Modal::SIZE_LARGE, 'toggleButton' => [ 'label' => '<i class="fa fa-image" aria-hidden="true"></i> ' . Yii::t('app', 'View Image'), 'class' => 'btn btn-default' ], ]); if(!empty($itemImage)) { echo "<img class='img-fluid' src='{$itemImage}' alt='Item Image'>"; } else { echo "<img class='img-fluid' src='data:image/png;base64," . base64_encode(\app\models\Tool::generateEmptyPng()) . "'/>"; } echo '<div class="modal-footer">'; echo ' <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>'; echo '</div>'; yii\bootstrap\Modal::end(); ?>
Modal Content (called from GridView field)
<?php Pjax::begin(); ?> <?= GridView::widget([ 'dataProvider' => $dataProvider, 'filterModel' => $searchModel, 'columns' => [ ['class' => 'yii\grid\SerialColumn'], 'id', 'account_number', 'contact', 'company_name', //... [ // use Modal window to display Notes 'attribute' => 'notes', 'label' => 'Notes', 'format' => ['raw'], 'value' => function($data) { if (!empty($data["notes"])) { $str = ' <!-- Button trigger modal --> <button type="button" class="btn btn-default btn-sm" data-toggle="modal" data-target="#modalNotes'.$data['id'].'"> <span class="glyphicon glyphicon-option-horizontal"></span> </button> <!-- Modal --> <div class="modal fade" id="modalNotes'.$data['id'].'" tabindex="-1" role="dialog" aria-labelledby="modalLabel'.$data['id'].'"> <div class="modal-dialog modal-lg" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> <h4 class="modal-title" id="modalLabel'.$data['id'].'">Notes</h4> </div> <div class="modal-body"> <pre>'. $data['notes'] . '</pre> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> </div> </div> </div> </div>'; } else { $str = ""; } return ($str); }, //'filter' => ['' => 'All', 1 => 'With Notes'] ], ['class' => 'yii\grid\ActionColumn'], ], ]); ?> <?php Pjax::end(); ?>
Modal View (called from GridView action)
Modal to view or update a record, called from a GridView
:
<?= yii\grid\GridView::widget([ 'dataProvider' => $dataProviderPrice, 'filterModel' => $searchModelPrice, 'tableOptions' => ['class' => 'table table-striped table-bordered table-hover'], 'columns' => [ // record number column ['class' => 'yii\grid\SerialColumn'], 'id', 'item_code', 'description', //['class' => 'yii\grid\ActionColumn'], [ 'class' => 'yii\grid\ActionColumn', //'template' => '{view} {update} {delete}', 'buttons' => [ 'view' => function ($url, $model) { return Html::a('<span class="glyphicon glyphicon-eye-open"></span>', $url , ['class' => 'view']); }, 'update' => function ($url, $model) { return Html::a('<span class="glyphicon glyphicon-pencil"></span>', $url , ['class' => 'update']); }, ], ], ], ]) ?> <?php // Attach click events to buttons 'View' and 'Update' $this->registerJs( "$(document).ready(function() { $('.view').click(function(e){ e.preventDefault(); $('#modalView').modal('show') .find('.modal-content') .load($(this).attr('href')); }); $('.update').click(function(e){ e.preventDefault(); $('#modalUpdate').modal('show') .find('.modal-content') .load($(this).attr('href')); }); }); "); ?> <?php // Modal for VIEW yii\bootstrap\Modal::begin([ 'id' => 'modalView', 'header' => '<b>' . Yii::t('app', 'View') . '</b>', 'footer' => Html::submitButton(Yii::t('app', 'Close')), //'toggleButton' => ['label' => '<span class="glyphicon glyphicon-eye-open"></span>', 'href' => yii\helpers\Url::to(['view'])], 'size' => yii\bootstrap\Modal::SIZE_LARGE, ]); echo "<div id='modal-content'></div>"; yii\bootstrap\Modal::end(); ?> <?php // Modal for UPDATE yii\bootstrap\Modal::begin([ 'id' => 'modalUpdate', 'header' => '<b>' . Yii::t('app', 'Update') . '</b>', 'footer' => Html::submitButton(Yii::t('app', 'Close')), //'toggleButton' => ['label' => '<span class="glyphicon glyphicon-pencil"></span>', 'href' => yii\helpers\Url::to(['update'])], 'size' => yii\bootstrap\Modal::SIZE_LARGE, ]); echo "<div id='modal-content'></div>"; yii\bootstrap\Modal::end(); ?>
See also: Yii2 Bootstrap Modal
Modal View (called from GridView action) using AJAX
To add a modal window (popup) from the index
view actions:
Add renderAjax()
call to your action:
public function actionView($id) { if (Yii::$app->request->isAjax) { $modal = ''; $modal .= '<div class="modal-header">'; $modal .= ' <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span></button>'; $modal .= ' <h4 class="modal-title" id="modalLabel">View</h4>'; $modal .= '</div>'; $modal .= '<div class="panel-body">'; $modal .= $this->renderAjax('view', ['model' => $this->findModel($id)]); $modal .= '</div>'; $modal .= '<div class="modal-footer">'; $modal .= ' <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>'; $modal .= '</div>'; return $modal; } else { return $this->render('view', [ 'model' => $this->findModel($id), ]); } }
In the view index
, add some AJAX code:
<?php use yii\helpers\Html; use yii\grid\GridView; use yii\widgets\Pjax; ?> <div class="price-index"> <!-- // ... --> <?php Pjax::begin(); ?> <?= GridView::widget([ 'dataProvider' => $dataProvider, 'filterModel' => $searchModel, 'columns' => [ ['class' => 'yii\grid\SerialColumn'], 'id', 'item_code', 'description', //... //['class' => 'yii\grid\ActionColumn'], [ 'class' => 'yii\grid\ActionColumn', 'buttons' => [ 'view' => function ($url, $model) { return Html::a('<span class="glyphicon glyphicon-eye-open"></span>', $url, ['class' => 'modal-view', 'data-pjax' => '0'] ); }, 'update' => function ($url, $model) { return Html::a('<span class="glyphicon glyphicon-pencil"></span>', $url, ['class' => 'modal-update', 'data-pjax' => '0'] ); }, ], ], ], ]); ?> <?php $this->registerJs( "$(document).on('ready pjax:success', function() { // 'pjax:success' when using pjax $('.modal-view').click(function(e){ e.preventDefault(); $('#modalView').modal('show') .find('.modal-content') .load($(this).attr('href')); }); $('.modal-update').click(function(e){ e.preventDefault(); $('#modalUpdate').modal('show') .find('.modal-content') .load($(this).attr('href')); }); }); "); yii\bootstrap\Modal::begin([ 'id' => 'modalView', 'header' => '<b>' . Yii::t('app', 'View') . '</b>', 'footer' => Html::submitButton(Yii::t('app', 'Close')), //'toggleButton' => [ // 'label' => '<span class="glyphicon glyphicon-eye-open"></span>', // 'href' => yii\helpers\Url::to(['view']) //], 'size' => yii\bootstrap\Modal::SIZE_LARGE, ]); echo "<div id='modal-content'></div>"; yii\bootstrap\Modal::end(); yii\bootstrap\Modal::begin([ 'id' => 'modalUpdate', 'header' => '<b>' . Yii::t('app', 'Update') . '</b>', 'footer' => Html::submitButton(Yii::t('app', 'Close')), //'toggleButton' => [ // 'label' => '<span class="glyphicon glyphicon-pencil"></span>', // 'href' => yii\helpers\Url::to(['update']) //], echo "<div id='modal-content'></div>"; 'size' => yii\bootstrap\Modal::SIZE_LARGE, ]); yii\bootstrap\Modal::end(); ?> <?php Pjax::end(); ?> </div>
Modal Confirmation (called from GridView action)
Example of confirmation dialog in a view:
<?php <?= yii\grid\GridView::widget([ 'dataProvider' => $dataProviderPrice, 'filterModel' => $searchModelPrice, 'tableOptions' => ['class' => 'table table-striped table-bordered table-hover'], 'columns' => [ // record number column ['class' => 'yii\grid\SerialColumn'], 'id', 'item_code', 'description', ['class' => 'yii\grid\ActionColumn'], [ // Checkboxes to delete selection 'class' => 'yii\grid\CheckboxColumn', 'footer' => getDeleteConfirmationDialog(), // Call Modal dialog ], ], 'showFooter' => true, ]) ?> <?php // Add Javascript code to perform AJAX call (using JQuery) $this->registerJs( "$(document).ready(function() { $('#modalConfirmDelete').on('hide.bs.modal', function (event) { var activeElement = $(document.activeElement); if (activeElement.is('[data-toggle], [data-dismiss]')) { console.log(activeElement); console.log('Button : ' + activeElement[0].textContent); var action = activeElement[0].textContent; switch(action) { case 'Delete': console.log('Deleting selected records. Action: ' + action); delSelected(); break; case 'Cancel': console.log('Canceled deletion. Action: ' + action); break; default: console.log('Nothing to be deleted. Action: ' + action); break; } } }); }); function delSelected() { if ( $( '#w5' ).length ) { var keys = $('#w5').yiiGridView('getSelectedRows'); // #w5 = col 5 in GridView for checkboxes console.log('Keys selected for deletion: ' + keys); $.post({ url:'". Yii::$app->homeUrl ."price/delete-selected', dataType: 'json', data: {keylist: keys}, success: function( data ) { console.log('Data Received: '); console.log(data.status); console.log(data.details); console.log(data.data_post); console.log(data.data_get); } }); } else { alert('No items available/selected for deletion.'); } } ", \yii\web\View::POS_END); ?> <?php function getDeleteConfirmationDialog() { $str = ''; $str .= '<!-- Button trigger modal -->'; $str .= '<button type="button" class="btn btn-default btn-sm" data-toggle="modal" data-target="#modalConfirmDelete">'; $str .= ' <span class="fa fa-trash-o" aria-hidden="true"></span>'; $str .= '</button>'; $str .= ''; $str .= '<!-- Modal -->'; $str .= '<div class="modal fade" id="modalConfirmDelete" tabindex="-1" role="dialog" aria-labelledby="modalLabelConfirmDelete">'; $str .= ' <div class="modal-dialog modal-sm" role="document">'; $str .= ' <div class="modal-content">'; $str .= ' <div class="modal-header">'; $str .= ' <button type="button" class="close" data-dismiss="modal" aria-label="Close">'; $str .= ' <span aria-hidden="true">×</span>'; $str .= ' </button>'; $str .= ' <h4 class="modal-title" id="modalLabelConfirmDelete">Delete</h4>'; $str .= ' </div>'; $str .= ' <div class="modal-body"><p>Delete selected records?</p></div>'; $str .= ' <div class="modal-footer">'; $str .= ' <button type="button" class="btn btn-alert" data-dismiss="modal">Delete</button>'; $str .= ' <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>'; $str .= ' </div>'; $str .= ' </div>'; $str .= ' </div>'; $str .= '</div>'; return $str; } ?>
The previous modal definition within getDeleteConfirmationDialog()
can be refactored at the end of the view as:
<?php <?= yii\grid\GridView::widget([ 'dataProvider' => $dataProviderPrice, 'filterModel' => $searchModelPrice, 'tableOptions' => ['class' => 'table table-striped table-bordered table-hover'], 'columns' => [ // record number column ['class' => 'yii\grid\SerialColumn'], 'id', 'item_code', 'description', ['class' => 'yii\grid\ActionColumn'], [ // Checkboxes to delete selection 'class' => 'yii\grid\CheckboxColumn', 'footer' => \yii\helpers\Html::button('<i class="fa fa-trash-o" aria-hidden="true"></i>', [ 'id' => 'btnDelete', 'class' => 'btn btn-default btn-sm', 'data-toggle' => 'modal', 'data-target' => '#modalConfirmDelete', ]), // Call Modal dialog ], ], 'showFooter' => true, ]) ?> <?php // Add Javascript code to perform AJAX call (using JQuery) $this->registerJs( "$(document).ready(function() { $('#modalConfirmDelete').on('hide.bs.modal', function (event) { var activeElement = $(document.activeElement); if (activeElement.is('[data-toggle], [data-dismiss]')) { console.log(activeElement); console.log('Button : ' + activeElement[0].textContent); var action = activeElement[0].textContent; switch(action) { case 'Delete': console.log('Deleting selected records. Action: ' + action); delSelected(); break; case 'Cancel': console.log('Canceled deletion. Action: ' + action); break; default: console.log('Nothing to be deleted. Action: ' + action); break; } } }); }); function delSelected() { if ( $( '#w5' ).length ) { var keys = $('#w5').yiiGridView('getSelectedRows'); // #w5 = col 5 in GridView for checkboxes console.log('Keys selected for deletion: ' + keys); $.post({ url:'". Yii::$app->homeUrl ."price/delete-selected', dataType: 'json', data: {keylist: keys}, success: function( data ) { console.log('Data Received: '); console.log(data.status); console.log(data.details); console.log(data.data_post); console.log(data.data_get); } }); } else { alert('No items available/selected for deletion.'); } } ", \yii\web\View::POS_END); ?> <?php // Modal for Delete yii\bootstrap\Modal::begin([ 'id' => 'modalConfirmDelete', 'header' => '<b>' . Yii::t('app', 'Delete') . '</b>', 'footer' => Html::submitButton(Yii::t('app', 'Delete'), [ 'class' => 'btn btn-danger', 'data-dismiss' => 'modal', 'data-action' =>'Delete' ]) . " " . Html::submitButton(Yii::t('app', 'Cancel'), [ 'class' => 'btn btn-default', 'data-dismiss' => 'modal', 'data-action' =>'Cancel' ]), //'toggleButton' => ['label' => '<span class="fa fa-trash-o"></span>', 'href' => yii\helpers\Url::to(['delete-selected'])], 'size' => yii\bootstrap\Modal::SIZE_SMALL, ]); echo "<div id='modal-content'>"; echo " <p>### Delete selected records?</p>"; echo "</div>"; yii\bootstrap\Modal::end(); ?>
In controller, add the action to call. Eg: actionDeleteSelected()
//... class PriceController extends Controller { public function behaviors() { return [ 'access' => [ 'class' => AccessControl::className(), 'rules' => [ [ 'actions' => [ 'index', 'delete-selected', //... ], 'allow' => true, 'roles' => ['@'], // @ = Authenticated users ], //... ], ], //... ]; } //... /** * Deletes selected Price models for specified customer. * @return mixed */ public function actionDeleteSelected() { if (Yii::$app->request->post('keylist')) { $keys = Yii::$app->request->post('keylist'); if (!is_array($keys)) { return \yii\helpers\Json::encode([ 'status' => 'error', 'details' => 'Not an array', ]); } if (count($keys) > 0) { $model = $this->findModel($keys[0]); $customer_id = $model->customer_id; // Method 1: Delete each record (using a loop) //foreach ($keys as $key => $id) { // $model = $this->findModel($id); // $model->delete(); //} // Method 2: Delete each record (using single query) $result = (new \yii\db\Query) ->createCommand() ->delete('price', ['in', 'id', $keys]) ->execute(); // Return Method 1: JSON //return \yii\helpers\Json::encode([ // 'status' => 'success', // 'details' => "Deleted items:\n" . implode(", ", $keys), //]); // Return Method 2: Redirect return $this->redirect(['customer/view', 'id' => $customer_id, 'tab'=>'price']); } } return \yii\helpers\Json::encode([ 'status' => 'error', 'details' => 'Not POST data', ]); }
See also: