Мое понимание
Глядя на вашу текущую реализацию, вы используете обычную отправку формы, хотя она заключена в контейнер Pjax
, но вы не включили отправку формы через Pjax
для своей формы и хотите показать спиннер или загрузчик, которые будут отображаться до тех пор, пока запрос к действию, когда вы отправляете запрос curl
в какой-либо API, завершается.
Ограничения
Что-то, что вам нужно понять, это то, что, если вы делаете обычную отправку формы и пытаетесь показать спиннер для какого-то процесса, который вы выполняете внутри controller/action
, он не будет работать, так как представление еще не визуализировано и ваш спиннер связан с любой javascript
или CSS
еще не отображается в браузере и не будет отображаться.
Решение
С другой стороны, если вы используете ajax
или pjax
для отправки формы, поскольку вы уже завернули форму в контейнер Pjax
, вы можете использовать события Pjax
с включением счетчика из AdminBSBTheme , который использует CSS только для отображения счетчика.
Это не просто работает для ваших форм ajax, но вы можете использовать его в целом на сайте для обычной загрузки страниц, оставляя приятный эффект. Он автоматически скрывается, когда DOM
готов, в случае медленного подключения к Интернету он выглядит более выровненным.
Включить Pjax в форме
Вы должны добавить атрибут data-pjax="1"
в тег формы, чтобы включить Pjax
отправку формы, она не будет работать по умолчанию, поэтому измените следующую строку, чтобы включить Pjax
отправку для формы.
<?php echo Html::beginForm(['process'],'post', ['data' => ['pjax' => 1]);?>
Тайм-аут включения для Pjax
Затем вам нужно указать свойство параметра timeout
, если ваш запрос curl
занимает немного времени, лучше добавить высокое значение для свойства timeout
, чтобы оно не выдавало loading request failed
или * 1046. * ошибка и ждет ответа. Давайте дадим ему 10 seconds
, поэтому, если для выполнения запроса требуется 10 secs
, его следует ждать, в противном случае продолжить, если получен ответ
.
<?php Pjax::begin(['timeout'=>10000]); ?>
Интеграция счетчика
Теперь пришла часть интеграции с вращателем, вы можете увидеть, как она работает в демонстрации ниже, она основана только на CSS.
Скопируйте Html
из демонстрации ниже в ваш файл views\layouts\main.php
после $this->beginBody()
и
добавьте css
в ваш файл site.css
или создайте отдельный файл и включите в файл AppAssets.php
.
/ Page Loader ================================= /
.page-loader-wrapper {
z-index: 99999999;
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
width: 100%;
height: 100%;
background: #eee;
overflow: hidden;
text-align: center;
}
.page-loader-wrapper p {
font-size: 13px;
margin-top: 10px;
font-weight: bold;
color: #444;
}
.page-loader-wrapper .loader {
position: relative;
top: calc(50% - 30px);
}
/ Preloaders ================================== /
.md-preloader .pl-red {
stroke: #F44336;
}
.md-preloader .pl-pink {
stroke: #E91E63;
}
.md-preloader .pl-purple {
stroke: #9C27B0;
}
.md-preloader .pl-deep-purple {
stroke: #673AB7;
}
.md-preloader .pl-indigo {
stroke: #3F51B5;
}
.md-preloader .pl-blue {
stroke: #2196F3;
}
.md-preloader .pl-light-blue {
stroke: #03A9F4;
}
.md-preloader .pl-cyan {
stroke: #00BCD4;
}
.md-preloader .pl-teal {
stroke: #009688;
}
.md-preloader .pl-green {
stroke: #4CAF50;
}
.md-preloader .pl-light-green {
stroke: #8BC34A;
}
.md-preloader .pl-lime {
stroke: #CDDC39;
}
.md-preloader .pl-yellow {
stroke: #ffe821;
}
.md-preloader .pl-amber {
stroke: #FFC107;
}
.md-preloader .pl-orange {
stroke: #FF9800;
}
.md-preloader .pl-deep-orange {
stroke: #FF5722;
}
.md-preloader .pl-brown {
stroke: #795548;
}
.md-preloader .pl-grey {
stroke: #9E9E9E;
}
.md-preloader .pl-blue-grey {
stroke: #607D8B;
}
.md-preloader .pl-black {
stroke: #000000;
}
.md-preloader .pl-white {
stroke: #ffffff;
}
.preloader {
display: inline-block;
position: relative;
width: 50px;
height: 50px;
-webkit-animation: container-rotate 1568ms linear infinite;
-moz-animation: container-rotate 1568ms linear infinite;
-o-animation: container-rotate 1568ms linear infinite;
animation: container-rotate 1568ms linear infinite;
}
.preloader.pl-size-xl {
width: 75px;
height: 75px;
}
.preloader.pl-size-l {
width: 60px;
height: 60px;
}
.preloader.pl-size-md {
width: 50px;
height: 50px;
}
.preloader.pl-size-sm {
width: 40px;
height: 40px;
}
.preloader.pl-size-xs {
width: 25px;
height: 25px;
}
.spinner-layer {
position: absolute;
width: 100%;
height: 100%;
border-color: #F44336;
-ms-opacity: 1;
opacity: 1;
-webkit-animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
-moz-animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
-o-animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
}
.spinner-layer.pl-red {
border-color: #F44336;
}
.spinner-layer.pl-pink {
border-color: #E91E63;
}
.spinner-layer.pl-purple {
border-color: #9C27B0;
}
.spinner-layer.pl-deep-purple {
border-color: #673AB7;
}
.spinner-layer.pl-indigo {
border-color: #3F51B5;
}
.spinner-layer.pl-blue {
border-color: #2196F3;
}
.spinner-layer.pl-light-blue {
border-color: #03A9F4;
}
.spinner-layer.pl-cyan {
border-color: #00BCD4;
}
.spinner-layer.pl-teal {
border-color: #009688;
}
.spinner-layer.pl-green {
border-color: #4CAF50;
}
.spinner-layer.pl-light-green {
border-color: #8BC34A;
}
.spinner-layer.pl-lime {
border-color: #CDDC39;
}
.spinner-layer.pl-yellow {
border-color: #ffe821;
}
.spinner-layer.pl-amber {
border-color: #FFC107;
}
.spinner-layer.pl-orange {
border-color: #FF9800;
}
.spinner-layer.pl-deep-orange {
border-color: #FF5722;
}
.spinner-layer.pl-brown {
border-color: #795548;
}
.spinner-layer.pl-grey {
border-color: #9E9E9E;
}
.spinner-layer.pl-blue-grey {
border-color: #607D8B;
}
.spinner-layer.pl-black {
border-color: #000000;
}
.spinner-layer.pl-white {
border-color: #ffffff;
}
.right {
float: right !important;
}
.gap-patch {
position: absolute;
top: 0;
left: 45%;
width: 10%;
height: 100%;
overflow: hidden;
border-color: inherit;
}
.gap-patch.circle {
width: 1000%;
left: -450%;
}
.circle-clipper {
display: inline-block;
position: relative;
width: 50%;
height: 100%;
overflow: hidden;
border-color: inherit;
}
.circle-clipper .circle {
width: 200%;
height: 100%;
border-width: 3px;
border-style: solid;
border-color: inherit;
border-bottom-color: transparent !important;
-ms-border-radius: 50%;
border-radius: 50%;
-webkit-animation: none;
animation: none;
position: absolute;
top: 0;
right: 0;
bottom: 0;
}
.circle-clipper.left .circle {
left: 0;
border-right-color: transparent !important;
-webkit-transform: rotate(129deg);
-moz-transform: rotate(129deg);
-ms-transform: rotate(129deg);
-o-transform: rotate(129deg);
transform: rotate(129deg);
-webkit-animation: left-spin 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
-moz-animation: left-spin 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
-o-animation: left-spin 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
animation: left-spin 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
}
.circle-clipper.right .circle {
left: -100%;
border-left-color: transparent !important;
-webkit-transform: rotate(-129deg);
-moz-transform: rotate(-129deg);
-ms-transform: rotate(-129deg);
-o-transform: rotate(-129deg);
transform: rotate(-129deg);
-webkit-animation: right-spin 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
-moz-animation: right-spin 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
-o-animation: right-spin 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
animation: right-spin 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
}
@-webkit-keyframes container-rotate {
to {
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-ms-transform: rotate(360deg);
-o-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes container-rotate {
to {
-moz-transform: rotate(360deg);
-ms-transform: rotate(360deg);
-o-transform: rotate(360deg);
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@-webkit-keyframes fill-unfill-rotate {
12.5% {
-webkit-transform: rotate(135deg);
transform: rotate(135deg);
}
25% {
-webkit-transform: rotate(270deg);
transform: rotate(270deg);
}
37.5% {
-webkit-transform: rotate(405deg);
transform: rotate(405deg);
}
50% {
-webkit-transform: rotate(540deg);
transform: rotate(540deg);
}
62.5% {
-webkit-transform: rotate(675deg);
transform: rotate(675deg);
}
75% {
-webkit-transform: rotate(810deg);
transform: rotate(810deg);
}
87.5% {
-webkit-transform: rotate(945deg);
transform: rotate(945deg);
}
to {
-webkit-transform: rotate(1080deg);
transform: rotate(1080deg);
}
}
@keyframes fill-unfill-rotate {
12.5% {
transform: rotate(135deg);
}
25% {
transform: rotate(270deg);
}
37.5% {
transform: rotate(405deg);
}
50% {
transform: rotate(540deg);
}
62.5% {
transform: rotate(675deg);
}
75% {
transform: rotate(810deg);
}
87.5% {
transform: rotate(945deg);
}
to {
transform: rotate(1080deg);
}
}
@-webkit-keyframes left-spin {
from {
-webkit-transform: rotate(130deg);
-moz-transform: rotate(130deg);
-ms-transform: rotate(130deg);
-o-transform: rotate(130deg);
transform: rotate(130deg);
}
50% {
-webkit-transform: rotate(-5deg);
-moz-transform: rotate(-5deg);
-ms-transform: rotate(-5deg);
-o-transform: rotate(-5deg);
transform: rotate(-5deg);
}
to {
-webkit-transform: rotate(130deg);
-moz-transform: rotate(130deg);
-ms-transform: rotate(130deg);
-o-transform: rotate(130deg);
transform: rotate(130deg);
}
}
@keyframes left-spin {
from {
-moz-transform: rotate(130deg);
-ms-transform: rotate(130deg);
-o-transform: rotate(130deg);
-webkit-transform: rotate(130deg);
transform: rotate(130deg);
}
50% {
-moz-transform: rotate(-5deg);
-ms-transform: rotate(-5deg);
-o-transform: rotate(-5deg);
-webkit-transform: rotate(-5deg);
transform: rotate(-5deg);
}
to {
-moz-transform: rotate(130deg);
-ms-transform: rotate(130deg);
-o-transform: rotate(130deg);
-webkit-transform: rotate(130deg);
transform: rotate(130deg);
}
}
@-webkit-keyframes right-spin {
from {
-webkit-transform: rotate(-130deg);
-moz-transform: rotate(-130deg);
-ms-transform: rotate(-130deg);
-o-transform: rotate(-130deg);
transform: rotate(-130deg);
}
50% {
-webkit-transform: rotate(5deg);
-moz-transform: rotate(5deg);
-ms-transform: rotate(5deg);
-o-transform: rotate(5deg);
transform: rotate(5deg);
}
to {
-webkit-transform: rotate(-130deg);
-moz-transform: rotate(-130deg);
-ms-transform: rotate(-130deg);
-o-transform: rotate(-130deg);
transform: rotate(-130deg);
}
}
@-moz-keyframes right-spin {
from {
-moz-transform: rotate(-130deg);
-ms-transform: rotate(-130deg);
-o-transform: rotate(-130deg);
-webkit-transform: rotate(-130deg);
transform: rotate(-130deg);
}
50% {
-moz-transform: rotate(5deg);
-ms-transform: rotate(5deg);
-o-transform: rotate(5deg);
-webkit-transform: rotate(5deg);
transform: rotate(5deg);
}
to {
-moz-transform: rotate(-130deg);
-ms-transform: rotate(-130deg);
-o-transform: rotate(-130deg);
-webkit-transform: rotate(-130deg);
transform: rotate(-130deg);
}
}
@keyframes right-spin {
from {
-moz-transform: rotate(-130deg);
-ms-transform: rotate(-130deg);
-o-transform: rotate(-130deg);
-webkit-transform: rotate(-130deg);
transform: rotate(-130deg);
}
50% {
-moz-transform: rotate(5deg);
-ms-transform: rotate(5deg);
-o-transform: rotate(5deg);
-webkit-transform: rotate(5deg);
transform: rotate(5deg);
}
to {
-moz-transform: rotate(-130deg);
-ms-transform: rotate(-130deg);
-o-transform: rotate(-130deg);
-webkit-transform: rotate(-130deg);
transform: rotate(-130deg);
}
}
<!-- Page Loader -->
<div class="page-loader-wrapper">
<div class="loader">
<div class="preloader">
<div class="spinner-layer pl-red">
<div class="circle-clipper left">
<div class="circle"></div>
</div>
<div class="circle-clipper right">
<div class="circle"></div>
</div>
</div>
</div>
<p>Please wait...</p>
</div>
</div>
<!-- #END# Page Loader -->
Затем добавьте следующую строку поверх views\layouts\main.php
файла
$js = <<<JS
setTimeout(function () {
$('.page-loader-wrapper').fadeOut();
}, 50);
JS;
$this->registerJs($js, \yii\web\View::POS_READY);
Примечание: в идеале вы можете обернуть все, что связано со счетчиком, в отдельный файл ресурсов и вызвать его в основном макете, но я оставлю эту часть вам.
До этого момента, если вы попытаетесь щелкнуть любую из ссылок в вашем приложении, вы увидите, что счетчик работает для ваших обычных загрузок страниц, таких как домашняя страница или любая другая.
Включение запросов Pjax
Нам нужно включить его и для Pjax
, поэтому перейдите к файлу view
и добавьте следующий фрагмент javascript сверху, который использует событие pjax:beforeSend
, чтобы показать счетчик
$js = <<<JS
$(document).on("pjax:beforeSend",function(){
$('.page-loader-wrapper').fadeIn();
});
JS;
$this->registerJs($js, \yii\web\View::POS_READY);
Вам не нужно беспокоиться о закрытии счетчика, он будет закрыт после загрузки страницы после ответа скручивания через наш основной код Layout.
Обновление
Причина, по которой значение кнопки отправки не передается при использовании pjax, является известной проблемой, см. здесь . Что вы можете сделать, это добавить 2 скрытых поля для 2 кнопок отправки и обновить значение соответствующего скрытого поля, связанного с кнопкой при нажатии, и отправить их вместе с формой и проверить значение для этих новых скрытых входов, поэтому что вы можете определить, какая кнопка была нажата.
Итак, сначала мы добавим скрытые входные данные, обратите внимание на опции, используемые для оригинального submitButton
rco, и dco, где должен быть идентификатор.
<?php echo Html::beginForm(['about'], 'post', ['data' => ['pjax' => 1]]); ?>
<?php echo Html::submitButton('Disconnect', ['class' => 'btn btn-success', 'id' => 'dco']) ?>
<?php echo Html::submitButton('Connect', ['class' => 'btn btn-info', 'id' => 'rco']) ?>
<?php echo Html::hiddenInput('dco', '', ['id' => 'dco_input']); ?>
<?php echo Html::hiddenInput('rco', '', ['id' => 'rco_input']); ?>
Теперь мы заменим javascript, который мы добавили ранее в нашем представлении, следующим:
$js = <<<JS
function loader(){
$('.page-loader-wrapper').fadeOut();
//reset the input values
$("#dco_input,#rco_input").val('');
//assign respective values to the associated hidden fields
$("#rco,#dco").on('click',function(e){
var buttonId = $(this).attr('id');
$("#"+buttonId+"_input").val(1);
});
}
$(document).on("pjax:beforeSend",function(e){
$('.page-loader-wrapper').fadeIn();
}).on("pjax:end",function(){
loader();
});
loader();
JS;
$this->registerJs($js, View::POS_READY);
?>
Теперь, когда мы нажмем кнопку dco
submit, скрытый ввод dco_input
будет заполнен 1
и при нажатии кнопки rco
отправить rco_input
будет обновлено до значения 1
перед отправкой for, и вы получите значение в post для обеих кнопок.
Последнеевам нужно изменить проверки вашего контроллера / действия process()
, которые проверяют isset($_POST['dco'])
и isset($_POST['rco'])
, которые не будут работать и должны быть обновлены
if(isset($_POST['dco']))
с помощью
if(isset($_POST["dco"]) && $_POST['dco']==1)
и
if(isset($_POST['rco']))
с
if(isset($_POST['rco']) && $_POST['rco']==1)