Yii2 Form in Modal Window

2019-04-02 17:00发布

问题:

I would like to understand the basics of how to work with form from Modal window in Yii2? This is my current understanding and I will be grateful if someone can explain me what I missed. So, I have a ListView with records. Each record contains a button. The button opens a Modal with a Form inside:

echo Html::a('<span class="glyphicon glyphicon-bell" aria-hidden="true"></span>', ['#'],[
                         'id' => $model->id,
                         'class' => 'linkbutton',
                         'data-toggle'=>'modal',
                         'data-tooltip'=>'true',
                         'data-target'=>'#submit_vote'.$model->id,
                         'title'=> 'Assign'
                     ]);

                Modal::begin([
                    'size' => 'modal-lg',
                    'options' => [
                        'id' => 'submit_vote'.$model->id,
                    ],
                    'header' => '<h2>Create Vote</h2>',
                    'footer' => 'Footer'
                ]);

                ActiveForm::begin([
                    'action' => 'vote/vote',
                    'method' => 'post',
                    'id' => 'form'.$model->id
                ]);

                echo Html::input(
                        'type: text',
                        'search',
                        '',
                        [
                            'placeholder' => 'Search...',
                            'class' => 'form-control'
                        ]
                );

                echo Html::submitButton(
                        '<span class="glyphicon glyphicon-search"></span>',
                        [
                            'class' => 'btn btn-success',
                        ]
                );
                ActiveForm::End();
                Modal::end();

In Form 'action' I wrote vote/vote and method post. So I expect post data inside actionVote function of my VoteController.

public function actionVote()
    {
        if (Yii::$app->request->post()) {
        $id = Yii::$app->request->post('search');
        Yii::$app->session->setFlash('error', $id);
        return true; 
        }
    }

For submitting I use an ajax:

$('form').on('submit', function () {
    alert($(this).attr('id')+$(this).attr('action')+$(this).serialize());  //just to see what data is coming to js
    if($(this).attr('id') !== 'searchForm') {  //some check
            $.ajax({
            url: $(this).attr('action'),
            type: 'post',
            data: $(this).serialize(),
            success: function(){
                $("#submit_vote15").modal('hide'); //hide popup  
            },
        });  
        return false;
    }

But after click on Submit form I see two alerts. Modal also not hidden. Flash message also is not showed. What I am doing wrong? Can anyone clearly explain a step by step procedure of data flow? For now my understanding is:

  1. Open Modal;
  2. Click Form Submit inside Modal;
  3. Load data via ajax to controller action;
  4. catch data from post and execute controller action code; What I missed?

回答1:

You may simply follow below step...

step1: define your link button like

<?php echo Html::a('<span class="glyphicon glyphicon-comment"></span>',
                    ['/feed/mycomment','id' => $model->id], 
                    [
                        'title' => 'View Feed Comments',
                        'data-toggle'=>'modal',
                        'data-target'=>'#modalvote',
                    ]
                   );
?>

step2: define your popup window(remote url)

<div class="modal remote fade" id="modalvote">
        <div class="modal-dialog">
            <div class="modal-content loader-lg"></div>
        </div>
</div>

step3: define your remote url action in your controller like

public function actionMyComment()
{
       $model = new MyComment();
       return $this->renderAjax('_add_comment', [
                'model' => $model,
        ]);

}

step4: define your view file _add_comment

<?php
use yii\helpers\Html;
use yii\bootstrap\ActiveForm;
?>
    <?php $form = ActiveForm::begin([ 'enableClientValidation' => true,
                'options'                => [
                    'id'      => 'dynamic-form'
                 ]]);
                ?>

      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal">&times;</button>
        <h4 class="modal-title">Add Comment</h4>
      </div>
      <div class="modal-body">
            <?php echo $form->field($model, 'name')->textInput(['maxlength' => true]) ?>
            <?php echo $form->field($model, 'email')->textInput(['maxlength' => true]) ?>
            <?php echo $form->field($model, 'comment')->textArea() ?>
      </div>
      <div class="modal-footer">
       <?php echo Html::submitButton(Yii::t('backend', 'Send'), ['class' => 'btn btn-success']) ?>
        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
      </div>
      <?php ActiveForm::end(); ?>

that's its...:)



回答2:

I see a few problems, first you're using on submit event, so yii fires once the event and the browser a second time (that's the reason the alert shows twice), you should use the beforeSubmit event. Second, the message doesn't appear because you're not rendering it again, your just setting it in your controller. To close the modal you should change your code to

$(".modal").modal('hide'); 

A usefull link is this



回答3:

Here Solution Yii2 Render a form in a Modal Popup using ajax

STEP 1 : BUTTON TO OPEN MODEL

<span  class="hand-cursor-pointer quick-add-contact" title="Add Contact"><i class="fa fa-plus-circle" aria-hidden="true"></i>Add Contact Via Model</span>

STEP 2 : JAVASCRIPT

<?php
$url = Yii::$app->urlManager->createUrl('modulesname/controllername/add-contact');

$script = <<< JS
//QUICK CREARE CONTACT MODEL
$(document).on('click', '.quick-add-contact', function () {       
    $('#addContactFormModel').modal('show').find('.modal-dialog').load('$url');
});

JS;
$this->registerJs($script);
?>

STEP 3 : MODEL HTML :

<!-- POPUP MODAL CONTACT -->                            
<div class="modal inmodal contact" id="addContactFormModel" role="dialog" data-keyboard="false" data-backdrop="static">
    <div class="modal-dialog modal-md "></div>
</div> 

STEP 4 : CONTROLLER

/**
 * Quick Add Contact Action
 * @param type $id
 * @return type
 */
public function actionAddContact() {

    $model = new ContactsManagement();

    if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
        $transaction = \Yii::$app->db->beginTransaction();          
        try {
            if ($model->validate()) {
                $flag = $model->save(false);
                if ($flag == true) {
                    $transaction->commit();                      
                    return Json::encode(array('status' => 'success', 'type' => 'success', 'message' => 'Contact created successfully.'));
                } else {
                    $transaction->rollBack();
                }
            } else {
                return Json::encode(array('status' => 'warning', 'type' => 'warning', 'message' => 'Contact can not created.'));
            }
        } catch (Exception $ex) {
            $transaction->rollBack();
        }
    }

    return $this->renderAjax('_add_form', [
                'model' => $model,
    ]);
}

/*
 * QUICK CREATE CONTACT FORM VALIDATION
 */

public function actionContactValidate() {
    $model = new ContactsManagement();
    if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
        $model->company_id = Yii::$app->user->identity->company_id;
        $model->created_at = time();
        \Yii::$app->response->format = Response::FORMAT_JSON;
        return ActiveForm::validate($model);
    }
}

STEP 5 : VIEW FILE

<div class="modal-content animated bounceInTop" >
    <?php
    $form = ActiveForm::begin(['id' => 'form-add-contact', 'enableAjaxValidation' => true, 'validationUrl' => Yii::$app->urlManager->createUrl('contacts/contacts/contact-validate')]);
    ?>
    <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal">&times;</button>
        <h4 class="modal-title text-left">Add Contact</h4>
    </div>
    <div class="modal-body">       
        <?= $form->field($model, 'name')->textInput(['maxlength' => true]) ?>
        <?= $form->field($model, 'emailid')->textInput(['maxlength' => true]) ?>
        <?= $form->field($model, 'mobile')->textInput(['maxlength' => true]) ?>
        <div class=" view-btn text-left"> 
            <?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-default' : 'btn btn-default']) ?>
            <button  type="button" class="btn btn-primary" data-dismiss="modal">Cancel</button>
        </div>
    </div>
    <?php ActiveForm::end(); ?>
</div>

<?php
$script = <<< JS

   $(document).ready(function () { 
        $("#form-add-contact").on('beforeSubmit', function (event) { 
            event.preventDefault();            
            var form_data = new FormData($('#form-add-contact')[0]);
            $.ajax({
                   url: $("#form-add-contact").attr('action'), 
                   dataType: 'JSON',  
                   cache: false,
                   contentType: false,
                   processData: false,
                   data: form_data, //$(this).serialize(),                      
                   type: 'post',                        
                   beforeSend: function() {
                   },
                   success: function(response){                      
                       toastr.success("",response.message); 
                       $('#addContactFormModel').modal('hide');
                   },
                   complete: function() {
                   },
                   error: function (data) {
                      toastr.warning("","There may a error on uploading. Try again later");    
                   }
                });                
            return false;
        });
    });       

JS;
$this->registerJs($script);
?>