Yii2 Pjax和ActiveForm在重新加载后提交不工作?

Mik*_*son 3 javascript pjax yii2

我正在我的提交按钮上创建一个加载指示器,并使用registerJs函数将"start"过程附加到beforeSubmit事件.

它第一次正常工作,但在重新加载Pjax容器后,再次提交表单时不会触发事件.

我将整个视图文件放在Pjax容器中,以便正确显示flash消息.

这是main.php布局文件片段:

<?php Pjax::begin([
'id' => 'pjax-container',
'enablePushState' => false,
]); ?>

<?= Alert::widget(); ?>

<?= $content; ?>

<?php Pjax::end(); ?>
Run Code Online (Sandbox Code Playgroud)

这里是registerJs函数,位于main.php中:

<?php
$js = <<< 'SCRIPT'
$('#form').on('beforeSubmit', function(){
alert('Submitted...');
//$("#spinner").fadeIn();
});
SCRIPT;
$this->registerJs($js);
?>
Run Code Online (Sandbox Code Playgroud)

这是activeForm:

<?php $form = ActiveForm::begin(['id' => 'form', 'options' => ['data-pjax' => true]]); ?>

<?= $form->field($model, 'name')->textInput(['type' => 'text']) ?>

<?= $form->field($model, 'email')->textInput(['type' => 'email']) ?>

<?= $form->field($model, 'subject')->textInput(['type' => 'text']) ?>

<?php
echo $form->field($model, 'message')->textArea(['rows' => 6]);

echo $form->field($model, 'verify_code')->widget(Captcha::className(), [
        'captchaAction' => 'site/captcha',
        'template' => '<div class="row"><div class="col-lg-4">{image}</div><div class="col-lg-6">{input}</div></div>',
]);
?>

<button class="btn btn-success">
<span id="spinner" style="display: none; float:left; margin-right: 26px;">
<?php
echo Spinner::widget([
'pluginOptions' => [
    'top' => '50%',
    'left' => '10px',
    'lines' => 11,
    'length' => 5,
    'width' => 3,
    'corners' => 1,
    'trail' => 100,
    'speed' => 1.25,
    'radius' => 4,
],
]);
?>
</span>
<?php echo $model->isNewRecord ? 'Send Message' : 'Update'; ?>
</button>

<?php ActiveForm::end(); ?>
Run Code Online (Sandbox Code Playgroud)

我正在使用Kartik Spinner Widget (详细信息和演示)

在成功提交后,Pjax加载数据容器后,有关为什么beforeSubmit事件不会触发的任何想法?

谢谢.

D.M*_*ill 5

出于多种原因会出现此问题.

首先,任何放在$(document).ready();ajax中并加载到ajax上的代码(包含的页面)在加载后都不会被执行.

其次,任何对外部脚本(<script src>)的引用都不保证在内联脚本之前加载.在Yii2的情况下,这些内联脚本将被注册registerJs()

让Pjax与复杂的脚本相关页面进行良好的加载并不是一件容易的事.

解决问题的一些方法:

1)如果通过视图呈现,则加载registerJs()和设置位置POS_READY(默认?)的内联脚本将包含在a中.$(document).ready()render()

因此,渲染via非常重要renderAjax().这将确保内联脚本将运行.

有时(大多数情况下)您需要render()在静态加载时以及renderAjax()pjax加载页面时使用.在您的实例中,这是将Pjax小部件放置在布局中所必需的.您可以在以下情况下使用以下代码:

if(Yii::$app->request->getHeaders()->has('X-PJAX'))
{
    return $this->renderAjax('myview');
}
else
{
    return $this->render('myview');
}
Run Code Online (Sandbox Code Playgroud)

2)编写外部脚本时,您知道将在pjax调用的上下文中加载.使用:

$(document).on('ready pjax:success', function(){
    // ...
});
Run Code Online (Sandbox Code Playgroud)

这将正确加载脚本.但请记住,每次Pjax调用成功时,它都会重新加载/重新绑定脚本.遗憾的是,这可能并不理想.

另请注意,在pjax:success加载包含页面的外部脚本后,事件不一定会触发.见3)

3)要解决脚本顺序问题,您需要从pjax.js脚本中删除以下行:

obj.scripts = findAll(obj.contents, 'script[src]').remove() 
Run Code Online (Sandbox Code Playgroud)

但是,这会对设置为禁用的浏览器产生问题eval()(因此首先存在该行的原因)

Pjax最终将这个排序.您可以在此处跟踪进度

如果有什么不清楚让我知道,我会改写.

更新: Yii 2.0.7引入了更改.其中一个是更新bower\yii2-pjax2.0.6.这使点3)不再必要,并且使点2)变得不那么重要,尽管知道它仍然是一件好事.