2

I'm trying to validate CActiveForm on modal dialog. I use bootstrap. The problem is modal dialog. When I read the contents of form during the load of main html page JavaScriopt validation works, but when I load the contents on click of button, validation scrips are gone. Here is the view of calling page

<?php
/* @var $this SiteController */

$this->pageTitle=Yii::app()->name . ' - Все магазины';
$this->breadcrumbs=array(
    'Shops',
);

$jsCreate = "$(\".createShop\").click(function(){
    var target = $(this).attr('data-target');
    var url = '?r=site/editShop';
    $(target).find(\".modal-dialog\").load(url);
});";
Yii::app()->getClientScript()->registerScript('create-shop-script',$jsCreate,CClientScript::POS_READY);

$jsEdit = "$(\".editShop\").click(function(){
    var target = $(this).attr('data-target');
    var url = $(this).attr('href');
    $(target).find(\".modal-dialog\").load(url);
});";
Yii::app()->getClientScript()->registerScript('edit-shop-script',$jsEdit,CClientScript::POS_READY);


$jsDelete = "$(\".deleteShop\").click(function(){
    var target = $(this).attr('data-target');
    var url = $(this).attr('href');
    $(target).find(\".modal-dialog\").load(url);
});";
Yii::app()->getClientScript()->registerScript('delete-shop-script',$jsDelete,CClientScript::POS_READY);
?>

<h2>Все объекты</h2>
 <!-- I created separate dialog for shop and warning because on open it shows the previous content while forming the new one 
      and I don't want to show shop elements on warning and vise versa -->
<!-- modal dialog for shop -->
<div id="shopModal" class="modal fade" aria-hidden="true" style="display: none;">
    <div class="modal-dialog">

    </div>
</div>

<!-- modal warning dialog -->
<div id="warningModal" class="modal fade" aria-hidden="true" style="display: none;">
    <div class="modal-dialog">

    </div>
</div>

<table class="table table-hover">
    <thead>
        <tr>
            <th>Название <span class="hidden-xs">объекта</span></th>
            <th><span class="glyphicon glyphicon-ok visible-xs"  data-toggle="tooltip" title="Статус активности"></span><span class="hidden-xs">Статус</span></th>
        </tr>
    </thead>
    <?php foreach($shops as $shop) :?>
    <?php $disabled = ($shop->active) ?'' :'gray'?>
    <tr>            
                <td><span class="<?php echo $disabled; ?>"><?php echo $shop->name; ?></span></td>
                <td>
                    <?php echo ($shop->active) ?"<span data-toggle='tooltip' title='Активен' class='glyphicon glyphicon-eye-open'></span>" :"<span data-toggle='tooltip' title='Неактивен' class='glyphicon glyphicon-eye-close'></span>" ?>
                    &nbsp; <a data-toggle='modal' data-target='#shopModal' class="editShop" href="?r=site/editShop&amp;id=<?php echo $shop->id; ?>"><span data-toggle='tooltip' title='Редактировать объект' class="glyphicon glyphicon-edit"></span></a>
                    &nbsp; <a data-toggle='modal' data-target='#warningModal' class="deleteShop" href="?r=site/deleteShop&amp;id=<?php echo $shop->id; ?>"><span data-toggle='tooltip' title='Удалить объект' class="glyphicon glyphicon-remove-circle"></span></a>
                </td>
    </tr>
    <?php endforeach; ?>
</table>
<button style='float:right;' data-toggle='modal' data-target='#shopModal' class="createShop btn btn-primary"><span data-toggle="tooltip" title="Добавить объект"><span class="glyphicon glyphicon-plus"></span> <span class="hidden-xs">Добавить объект</span></span></button>

This is the view of form, that appears inside modal dialog

<?php
/* 
   @var $this SiteController 
   @var $form CActiveForm */
?>
<?php
$form=$this->beginWidget('CActiveForm', array(
        'id'=>'shop-form',
        'enableClientValidation'=>true,
        'clientOptions'=>array(
                'validateOnSubmit'=>true,
        ),
        'htmlOptions'=> array('class'=>'bottom0',),
        'action'=>"$url&id={$model->id}",
));?>   
  <div class="modal-content panel-primary">
      <div class="modal-header panel-heading">
          <button type="button" class="close panel-title" data-dismiss="modal" aria-hidden="true"><span data-container="body" data-toggle="tooltip" title="Закрыть">×</span></button>  
        <h4 class="modal-title panel-title"><?php echo $title;?></h4>
      </div> <!-- end modal-header -->

      <div class="modal-body">
        <div class="form-group">              
              <?php echo $form->textField($model,'name',array('data-toggle'=>'tooltip', 'title'=>'Название', 'class'=>'form-control', 'placeholder'=>'Название', 'maxlength'=>'50')); ?>
              <?php echo $form->error($model,'name'); ?>
        </div>
          <div class="form-group">
              <label data-toggle="tooltip" title="Статус активноси">
                  <?php echo $form->checkBox($model,'active') .' '. $form->label($model,'active') . $form->error($model,'active'); ?>
              </label>
          </div>
      </div> <!-- end modal-body -->


      <div class="modal-footer">
          <!-- Save button -->
          <button type="submit" class="btn btn-primary"><span data-toggle="tooltip" title="Сохранить"><span class="glyphicon glyphicon-ok"></span> <span class="hidden-xs">Сохранить</span></span></button>
          <!-- Cancel button -->
          <button type="button" class="btn btn-default" data-dismiss="modal"><span data-toggle="tooltip" title="Отменить"><span class="glyphicon glyphicon-remove"></span> <span class="hidden-xs">Отменить</span></span></button>
     </div> <!-- end modal-footer -->
  </div>
 <?php $this->endWidget(); ?>

This is my Shops model

<?php

/**
 * This is the model class for table "shops".
 *
 * The followings are the available columns in table 'shops':
 * @property integer $id
 * @property string $name
 * @property string $active
 */

class Shops extends CActiveRecord
{

public function tableName()
{
    return 'shops';
}

public function rules()
{
    // NOTE: you should only define rules for those attributes that
    // will receive user inputs.
    return array(
        array('name', 'length', 'max'=>255),
        array('active', 'length', 'max'=>1),
        array('id, name, active', 'safe', 'on'=>'search'),
    );
}

public function relations()
{
    return array();
}

public function attributeLabels()
{
    return array(
        'id' => 'ID',
        'name' => 'Name',
        'active' => 'Active',
    );
}


public static function model($className=__CLASS__)
{
    return parent::model($className);
}
}

This is my site controller that deals with shop create/update/delete

public function actionEditShop($id=null)
{
        if (!$this->checkAuthenticated()) return;


       if(isset($_POST['ajax']) && $_POST['ajax']==='shop-form')
        {
          echo CActiveForm::validate($model);
            Yii::app()->end();
        }
        $model = $this->loadShop($id);
        if(isset($_POST['Shops']))
        {   
            // create/update shop               
            $fields = $_POST['Shops'];
            $fields['id'] = $id;
            $model->attributes=$fields;

            if($model->save())
                    $this->redirect(array('shops'));
        } else {
            // open form to create/update                
            $this->renderPartial('classifier',array('model'=>$model, 'title'=>'Объект', 'url'=>'?r=site/editShop'), false, true);
        }
}

    public function actionDeleteShop($id, $confirmed=null)
{
        if (!$this->checkAuthenticated()) return;
        $model = $this->loadShop($id);
        if (isset($confirmed)){
    $model->delete();
    $this->redirect(array('shops'));
        } else {
            $this->renderPartial('warning',array('url'=>"?r=site/deleteShop&id=$id&confirmed=1",));
        }
}

    private function loadShop($id=null)
{
        if ($id){
    $model=Shops::model()->findByPk($id);
    if($model===null)
        throw new CHttpException(404,"Объект под номером $id не существует.");
        } else {
            $model = new Shops; // creates with active='1'
            $model->active = '1';
        }
        return $model;
}
Jeff_Alieffson
  • 2,672
  • 29
  • 34

1 Answers1

0

You need to explicitly tell your controller to include your scripts using the processOutput parameter of renderPartial(). When set, processOutput() is called which:

Postprocesses the output generated by render(). This method is invoked at the end of render() and renderText(). If there are registered client scripts, this method will insert them into the output at appropriate places. If there are dynamic contents, they will also be inserted. This method may also save the persistent page states in hidden fields of stateful forms in the page.

You should also uncomment

$this->performAjaxValidation($model);

and look at Yii renderpartial (proccessoutput = true) Avoid Duplicate js request if you use processOutput.

Community
  • 1
  • 1
topher
  • 14,790
  • 7
  • 54
  • 70
  • I changed, but no way – Jeff_Alieffson Sep 19 '14 at 03:54
  • Are the validation scripts appearing in the code now? – topher Sep 19 '14 at 19:28
  • Sorry. There was an incorrect part. Now I changed all parts. Please note, that the form is loading on modal dialog after rendering the page, so the validation javascript does not appear on resulting page. I compared it with Yii login dialog. There are a couple of validation scrips that is not present after moving the form into modal dialog – Jeff_Alieffson Sep 20 '14 at 14:53
  • Are these missing scripts your own or the default Yii scripts? – topher Sep 21 '14 at 22:07