我正在我的提交按钮上创建一个加载指示器并附加" start"使用registerJs函数的beforeSubmit事件的过程。
第一次正常工作,但在重新加载Pjax容器后,当再次提交表单时,事件不会激活。
我将整个视图文件放在Pjax容器中,以便正确显示flash消息。
这是main.php布局文件片段:
<?php Pjax::begin([
'id' => 'pjax-container',
'enablePushState' => false,
]); ?>
<?= Alert::widget(); ?>
<?= $content; ?>
<?php Pjax::end(); ?>
这是registerJs函数,位于以下部分的main.php中:
<?php
$js = <<< 'SCRIPT'
$('#form').on('beforeSubmit', function(){
alert('Submitted...');
//$("#spinner").fadeIn();
});
SCRIPT;
$this->registerJs($js);
?>
这是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(); ?>
我使用的是Kartik Spinner Widget (Details and Demo)
在成功提交后,Pjax加载数据容器后,有关为什么beforeSubmit事件不会激活的任何想法?
感谢。
答案 0 :(得分:5)
出现此问题有几个原因。
首先,任何放在$(document).ready();
内并加载到ajax被称为页面(包含页面)的代码在加载后都不会被执行。
其次,任何对外部脚本(<script src>
)的引用都不保证在内联脚本之前加载。对于Yii2,这些内联脚本将在registerJs()
让Pjax与要加载的复杂脚本相关页面一起玩得很好不琐碎。
解决问题的一些方法:
1)如果视图为registerJs()
,那么加载了POS_READY
并且位置为$(document).ready()
(默认值为?)的内联脚本将包含在render()
中通过renderAjax()
呈现。
因此,通过render()
进行渲染非常重要。这将确保内联脚本将运行。
有时(大多数情况下)您需要在静态加载时使用renderAjax()
,在pjax加载页面时使用if(Yii::$app->request->getHeaders()->has('X-PJAX'))
{
return $this->renderAjax('myview');
}
else
{
return $this->render('myview');
}
。在您的实例中,这是将Pjax小部件放置在布局中所必需的。您可以在以下情况下使用以下代码:
$(document).on('ready pjax:success', function(){
// ...
});
2)编写您知道的外部脚本将在pjax调用的上下文中加载。使用:
pjax:success
这将正确加载脚本。但请记住,每次Pjax调用成功时,它都会重新加载/重新绑定脚本。遗憾的是,这可能并不理想。
另请注意,加载包含页面的外部脚本后,obj.scripts = findAll(obj.contents, 'script[src]').remove()
事件不一定会触发。见3)
3)要解决脚本订单问题,您需要从pjax.js脚本中删除以下行:
eval()
但是,这会对设置为禁用bower\yii2-pjax
的浏览器产生问题(因此首先存在该行的原因)
Pjax最终会对此进行排序。您可以跟踪进度here
如果有什么不清楚,请告诉我,我会改写。
更新: Yii 2.0.7引入了更改。其中一个是将2.0.6
更新为{{1}}。这使得点 3)不再必要,并使得 2)不那么重要,尽管它仍然是一件好事。
答案 1 :(得分:0)
因此。我有一个解决方案,但它与文档相矛盾......
如果你看一下实际的重定向功能(来源):
public function redirect($url, $statusCode = 302, $checkAjax = true)
743 {
744 if (is_array($url) && isset($url[0])) {
745 // ensure the route is absolute
746 $url[0] = '/' . ltrim($url[0], '/');
747 }
748 $url = Url::to($url);
749 if (strpos($url, '/') === 0 && strpos($url, '//') !== 0) {
750 $url = Yii::$app->getRequest()->getHostInfo() . $url;
751 }
752
753 if ($checkAjax) {
754 if (Yii::$app->getRequest()->getIsPjax()) {
755 $this->getHeaders()->set('X-Pjax-Url', $url);
756 } elseif (Yii::$app->getRequest()->getIsAjax()) {
757 $this->getHeaders()->set('X-Redirect', $url);
758 } else {
759 $this->getHeaders()->set('Location', $url);
760 }
761 } else {
762 $this->getHeaders()->set('Location', $url);
763 }
764
765 $this->setStatusCode($statusCode);
766
767 return $this;
768 }
你可以看到它在Ajax之前检查Pjax并且有两个不同的头。在整个网络和多个网站上提到的X-Redirect标头不适用于Pjax调用。您必须检查X-Pjax-Url是否有Pjax呼叫。
我注册了自己的javascript函数来处理重定向,如下所示:
$js = <<< 'SCRIPT'
$(document).on('pjax:complete', function (event, xhr, textStatus, options) {
//$(document).ajaxComplete(function (event, xhr, settings) {
var url = xhr.getResponseHeader('X-Pjax-Url');
if (url) {
window.location = url;
}
});
SCRIPT;
$this->registerJs($js);
由于某种原因,这本身还不够。默认情况下,源函数运行checkAjax代码,但在我从重定向代码中明确调用它之前,它将不起作用。
所以这就是我在控制器中使用的内容:
Yii::$app->response->redirect(Yii::getAlias('@web') . '/secure/dashboard/', true)->send();
return;
这已经讨论了很多次,我希望这有助于其他人。