Yii2 - предупреждающее сообщение перед отправкой

У меня есть форма с двумя полями "a" и "b", когда в действии обновляется, если поле "b" изменяет событие "beforeSubmit", модальное предупреждение Bootstrap отправляется пользователю без какой-либо кнопки OK или CANCEL, только информация в течение 5 секунд, по истечении этого времени автоматически сохраняется, если поле «b» действительно было изменено, если не изменяется, сохраняется без модальных окон предупреждений.

Как мне отправить это условие с контроллера, чтобы посмотреть, где у меня есть javascript? может с аяксом? но как?

Контроллер.php

public function actionUpdate()
    {
        $model = new Faqs();

        if ($model->load(Yii::$app->request->post()) && $model->save()) {

            if ($model->oldAttributes["b"] != $model->b){
                sleep(5);
            }

            return $this->redirect(['view', 'id' => $model->id]);
        } else {
            return $this->render('update', [
                'model' => $model,
            ]);
        }
    }

_form.php

$('#form').on('beforeSubmit', function(e) {
    if(old_B_attribute != current_B_attribute){ //example
        $('#modal').modal('show');
    }
});

person Moutinho    schedule 15.03.2019    source источник
comment
не ясно, что вы спрашиваете, также вы можете просто вызвать $model->getDirtyAttributes(), который фактически используется при сохранении или обновлении записи, чтобы определить, какие поля были фактически изменены.   -  person Muhammad Omer Aslam    schedule 15.03.2019
comment
@MuhammadOmerAslam Мне нужно показать модальное предупреждение перед отправкой только тогда, когда поле b было фактически изменено   -  person Moutinho    schedule 15.03.2019
comment
хорошо, и что должно произойти после отображения модального окна с предупреждением, есть ли какие-то кнопки OK и CANCEL в модальном окне, которые будут решать, что делать? вы должны добавить всю информацию в вопрос о том, когда следует отправлять форму, а когда нет? что должно произойти в случае, если значение не изменилось, что должно произойти при нажатии любой из кнопок OK или CANCEL (если они есть)   -  person Muhammad Omer Aslam    schedule 16.03.2019
comment
@MuhammadOmerAslam, без каких-либо кнопок OK или CANCEL, только информация в течение 5 секунд, по истечении этого времени автоматически сохраняется, если поле b было действительно изменено, если не изменяется, сохраняется без модальных окон предупреждений.   -  person Moutinho    schedule 16.03.2019


Ответы (3)


Вы хотите подсказать пользователю, действительно ли значения атрибутов были изменены перед отправкой формы.

Как бы я пошел на это

  • Создайте отдельное действие в моем контроллере actionAttributeDirty(), которое будет проверять, действительно ли выбранный атрибут был изменен.
  • Затем используйте для формы обычный Html::button(), а не Html::submitButton().
  • Добавьте скрытое поле для хранения текущих записей id в форме.
  • Привяжите событие click к кнопке, которая отправит ajax-вызов actionAttributeDirty() с id текущей записи.
  • Затем используйте функцию успеха, чтобы отобразить модальное окно, и используйте setTimeout с $.yiiActiveForm('submitForm'), чтобы инициировать отправку формы через 5 секунд.

Таким образом, в аналогичном порядке, указанном выше,

actionAttributeDirty

public function actionAttributeDirty()
{
    Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
    $id = Yii::$app->request->post('id');
    $model = Faqs::findOne($id);
    $response = ['changed' => false];
    $isValidRequest = Yii::$app->request->isAjax && Yii::$app->request->isPost;

    if ($isValidRequest && $model->load(Yii::$app->request->post())) {
        //get the name of the fields from the dirty attributes
        $changedAttributes = array_keys($model->getDirtyAttributes());

        //if the attribute name exists in the dirty attributes
        if (!empty($changedAttributes) && in_array("b", $changedAttributes)) {
            $response['changed'] = true;
        }
    }
    return $response;
}

Ваша форма должна иметь следующие кнопки вместе с другими полями:

$form = \yii\widgets\ActiveForm::begin(['id' => 'form']);
echo \yii\helpers\Html::hiddenInput('id', $model->id);
echo \yii\helper\Html::button('save', ['id' => 'save-now']);
\yii\widgets\ActiveForm::end();

click Событие для кнопки

Добавьте следующее в верхнюю часть представления, где у вас есть форма.

Примечание: измените url вызова ajax '/site/attribute-dirty' соответственно, где вы копируете actionAttributeDirty(), я предполагаю, что вы копируете его внутри контроллера сайта.

$js = <<< JS
    $('#save-now').on('click', function(e) {
        e.preventDefault();
        let form = $("#form");

        $.ajax({
            url:'/site/attribute-dirty',
            method:'post',
            data:form.serialize(),
        }).done(function(response){
            if(response.changed){
                $('#modal').modal('show');
                setTimeout(function(){form.yiiActiveForm('submitForm');}
                , 5000);
            }else{
                form.yiiActiveForm('submitForm');
            }

        }).fail(function(response){
            console.log(response.responseText);
        });
    });
JS;

$this->registerJs($js, \yii\web\View::POS_READY);

ИЗМЕНИТЬ

Нажатие кнопки Enter все равно не отправит форму, так как кнопки отправки нет. Если вы хотите, чтобы кнопка Enter отправила форму, вы должны добавить следующее вместе со сценарием также на верхняя часть представления, которая будет запускать событие click кнопки save-now всякий раз, когда кнопка Enter нажимается внутри любого ввода.

$("#form").on('keypress','input',function(e){
    e.preventDefault();
    if(e.keyCode===13){
        $("#save-now").trigger('click');
    }
});
person Muhammad Omer Aslam    schedule 16.03.2019
comment
фантастически, всегда готов помочь, в основном вы написали весь код для меня :) Спасибо! Я просто вижу, что отправка с помощью клавиши Enter сохраняется без запуска javascript, потому что событие $('#save-now').on('click', function(e) {}.. - person Moutinho; 17.03.2019
comment
я не думаю, что он должен даже отправлять форму при нажатии кнопки ввода @Moutinho вы изменили тип кнопки на обычную кнопку? - person Muhammad Omer Aslam; 17.03.2019
comment
см. раздел РЕДАКТИРОВАНИЕ @Moutinho - person Muhammad Omer Aslam; 17.03.2019
comment
да, я меняю кнопку на <?= Html::button('save', ['id' => 'save-now']); ?>, но когда я нажимаю ввод, она отправляется... - person Moutinho; 17.03.2019

ваш запрос не может быть выполнен на стороне клиента до отправки. Потому что вы должны принять решение на стороне сервера.

На стороне клиента вы можете использовать

$(document).on("beforeValidate", "form", function(event, messages, deferreds) {
//   #code
// console.log('BEFORE VALIDATE TEST');
}).on("afterValidate", "form", function(event, messages, errorAttributes) {
// console.log('AFTER VALIDATE TEST');
 //#code
});

Затем выберите метод rules.

На стороне сервера вы также можете выбрать следующие события: (для чего вы хотите)  beforeValidate, afterValidate,beforeSave,afterSave,...

person user206    schedule 16.03.2019
comment
Я не понимаю, как проверить, должно ли оно отображаться модально или нет (если поле b фактически не изменилось) на стороне клиента - person Moutinho; 16.03.2019

если вы хотите показать модальное подтверждение, я использую, как показано ниже. вы можете изменить в соответствии с вашими потребностями или скрыть отправку через x секунд

  $(function() {
    submitting = false;
  });

  $("form").on("beforeSubmit", function (event, messages, errorAttributes) {
    if (typeof(errorAttributes) === "undefined" || errorAttributes.length === 0) {
      $('#modal-confirm').modal('show');
      return submitting;
    }
  });

  var submit = function() {
    submitting = true;
    $("form").yiiActiveForm('submitForm');
  }

в модальном режиме

  <button type="button" onclick="submit();">Confirm</button>
person memo    schedule 17.03.2019