Modal causing multiple requests

This related to my other question https://forum.yiiframework.com/t/pass-pjax-id-to-modal-javascript/126740/2 but I thought I’d ask thing independently.

I have an index file listing all the projects with a Create button above the Pjax Gridview which is used to display the create view in a modal. If they update the modal and save, it commits the data and reload the pjax container.

The issue is, the first time they use the modal, all is good. However, subsequent call generate an increasing number of update requests. Seems to keep all the previous requests in memory and reissue them.

Now the solution I found, https://forum.yiiframework.com/t/solved-pjax-in-remote-modal-cause-multiple-request/82621, is to use a unique pjax container id in the index using uniqid(), but the issue I’m having with this is that then the modal form’s pjax.reload reloads the entire page and not just the pjax container.

What is the way to handle this situation? Is the uniqid the solution, if so, how to make the reload work properly? If not, how to avoid the multiple request issue?

Thank you for your help in advance,

Below is the code involved
My index code looks like

<div class="projects-index">
    <p><div id="message"></div></p>
    <p>
        <?= Html::button('<i class="glyphicon glyphicon-plus"></i> '.Yii::t('app', 'New Booking'), 
            [
                'id'=>'modalCreateButton',
                'class' => 'btn btn-success modalButton', 
                'value'=>Url::to('index.php?r=projects/create'), 
                'title'=>Yii::t('app', 'New Booking'),
            ]) 
        ?>
    </p>
<div id="gridContainer">
<?php
$pjaxContainerName = 'pjaxContainer_';
Pjax::begin([
        'id' => $pjaxContainerName,
        'enablePushState' => false,
        // 'enableReplaceState' => false,
        'options' => [
            'data-pjax' => true, 
            'class' => 'pjaxProjectsContainer'
        ],
        'scrollTo' => false,
        'timeout' => 5000,
    ]); ?>
    <?= GridView::widget([
        'id' => 'grid',
        'dataProvider' => $dataProvider,
        'filterModel' => $searchModel,

my js for the Create button is

 $('.modalButton').click(function () {
	$('#loading').show();
	$('#modal').modal('show')
		.find('#modalContent')
		.load($(this).attr('value'));
	document.getElementById('modalHeaderTitle').innerHTML = '<h4>' + $(this).attr('title') + '</h4>';
	$.fn.modal.Constructor.prototype.enforceFocus = function() {}; //Fix for Select2 modal issue.
	return false; //Stop default link reloading of page
});

and my modal is defined as

Modal::begin([
    'id'=>'modal',
    'class'=>'modal',
    'size'=>'modal-lg',
    'headerOptions' => ['id' => 'modalHeader'],
    'header' => '<span id="modalHeaderTitle"></span>',
    'closeButton' => [
        'label'=>'Cancel',
        'id'=>'close-button2',
        'class'=>'btn btn-warning pull-right',
        'title'=>'Close without saving',
    ],
    'clientOptions' => [
        'backdrop' => 'static', // true,
        'keyboard' => false, // true,
    ]
]);
echo '<div id="modal-system-messages"></div>';
echo '<div id="passInfo" style="opacity: 1; display: none"><input type="hidden" name="pjaxId" id="pjaxId" value="'.$pjaxContainerName.'"/></div>';
echo "<div id='modalContent'></div>";
Modal::end();

If pjax widget contains unique ID, then you should not try to render it again. In my case I placed such pjax in layout and rendered response without layout on save/update request.

I won’t share my original code, but it roughly looks like following:

  • controllers\PostControler.php:
public function actionAddComment($post_id)
{
    $this->layout = 'modal';
    $model = new CommentForm;
    $post = $this->findModel($post_id);
    if ($model->load(Yii::$app->request->post())) {
        $this->layout = false; // render only updated content, not layout with pjax
        if ($model->validate() && $model->save()) {
            $message = "Success!";
        } else {
            $message = "Error :(";
        }
        return $this->render('add_comment', compact('model', 'post', 'message'));
    }
    return $this->render('add_comment', compact('model', 'post'));
}
  • views/layouts/modal.php:
<?php $this->beginPage() ?>
<!DOCTYPE html>
<html lang="<?= Yii::$app->language ?>">
    <head>
        <?php $this->head() ?>
    </head>
    <body>
        <?php $this->beginBody() ?>

        <div class="modal-header">
            <div class="bootstrap-dialog-header">
                <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
                <h4 class="bootstrap-dialog-title modal-title"><?= Html::encode($this->modalTitle); // custom member in my View class ?></h4>
            </div>
        </div>
        <div class="modal-body">
            <div class="bootstrap-dialog-body">
                <?php yii\widgets\Pjax::begin(['id' => 'pjax_form_'.uniqid(), 'enablePushState'=>false, 'timeout' => 5000]) ?>
                    <?= $content; ?>
                <?php yii\widgets\Pjax::end() ?>
            </div>
        </div>
        <?php $this->endBody() ?>
    </body>
</html>
<?php $this->endPage() ?>
  • views/post/add_comment.php:
<?php
...
$this->modalTitle = "Add comment";
?>
<?php if(isset($message) && !empty($message)): ?>
    <p class="mb15">
        <?= $message; ?>
    </p>
<?php else: ?>
    <?php $form = ActiveForm::begin(['id' => 'add-comment', 'options' => ['data-pjax' => true]]); ?>
        ... YOUR FORM FIELDS HERE ...
        <div class="form-group">
            <?= Html::submitButton('Add') ?>
        </div>
    <?php ActiveForm::end(); ?>
<?php endif; ?>

Hope this helps!