Yii 1.1: sformwizard

Turn your normal form into a multi step ajax form with minimal effort!
26 followers

SFormWizard is a wrapper for http://thecodemine.org

Features: Turn a normal form into a multi-step ajax form in no time. A bunch of events,options and methods (see link above).

Installation: unzip to protected/extensions/sformwizard

Make sure your form has an id (or other unique identifier)

Then, divide your normal form into steps by adding class="step" to any div AND give each div an unique id. this id can be anything. To use other elements then a div tag, please see http://thecodemine.org Leave the submit button outside of the steps Example:

...
<div class="step" id="Step1">
<div class="row">
 <p class="note">Fields with <span class="required">*</span> are required.</p>
 
 <?php echo $form->labelEx($model,'title'); ?>
 <?php echo $form->textField($model,'title',array('size'=>80,'maxlength'=>128)); ?>
 <?php echo $form->error($model,'title'); ?>
</div>
<div class="row">
 <?php echo $form->labelEx($model,'content'); ?>
 <?php echo CHtml::activeTextArea($model,'content',array('rows'=>10, 'cols'=>70)); ?>
 <p class="hint">You may use <a target="_blank" href="http://daringfireball.net/projects/markdown/syntax">Markdown syntax</a>.</p>
 <?php echo $form->error($model,'content'); ?>
</div>
</div>
...

Minimum code:

<?php          
 $this->widget('ext.sformwizard.SFormWizard',array(
    'selector'=>"#post-form", //change this to the jquery selector for your form
    ));
 ?>

All options and their default values (see SFormWizard.php for description of each or visit http://thecodemine.org

<?php          
 $this->widget('ext.sformwizard.SFormWizard',array(
    'selector'=>"#post-form",
    'historyEnabled' =>"false",
    'validationEnabled' => "false",
    'validationOptions' => "undefined",
    'formPluginEnabled' => "false",
    'formOptions' => '{ reset: "true",}, success: function(data) {        alert("success"); }',
    'linkClass' =>".link",
    'submitStepClass' =>".submit_step",
    'back' => ":reset",
    'next' => ":submit",
    'textSubmit' => "Submit",
    'textNext' => "Next",
    'textBack' =>"Back",
    'remoteAjax' =>"undefined",
    'inAnimation' => "{opacity:'show'}",
    'outAnimation' => "{opacity:'hide'}",
    'inDuration' => 400,
    'outDuration' => 400,
    'easing' => "swing",
    'focusFirstInput' => "false",
    'disableInputFields' => "true",
    'disableUIStyles' => "false",
    'jsAfterStepShown'=>    '',
    ));
?>

A more complex but far from full featured example that uses ajax: For this we need to slightly modify out controller action. This is the how it should look in the blog demo (PostController). Note you can customize as much if you want if you understand the code.

public function actionCreate()
{
  $model=new Post;
 if(isset($_POST['Post']))
 { 
  $model->attributes=$_POST['Post'];
  if($model->save()){
  if(Yii::app()->request->isAjaxRequest){
   $comment=$this->newComment($model);
   $link = CHtml::link('Click here to see your new post','view?id='.$model->id);
   echo CJSON::encode($link);
   exit;
  }
  //if the form is submitted without ajax           
  $this->redirect(array('view','id'=>$model->id));
   }else{
     if(Yii::app()->request->isAjaxRequest){
      echo CJSON::encode("Error! Could not save the model");
     exit;
     }
    }
   }
   $this->render('create',array(
    'model'=>$model,
    ));
 }

Next: Add a couple of placeholder divs below your form

<div id="stepmessage"></div>
<div id="data"></div>

And then the widgetcall:

<?php              
  $this->widget('ext.sformwizard.SFormWizard',array(
   'selector'=>"#post-form",
   'historyEnabled' =>"true",
   'validationEnabled' => "true",
   'validationOptions' => "undefined",
   'formPluginEnabled' => "true",
   'formOptions' => '{
    success: function(data){$("#stepmessage").fadeTo(500,1,function(){    $("#stepmessage").html(data); })},
    beforeSubmit: function(data){
    $("#data").html("data sent to the server: " + $.param(data));
    },
    dataType: "json",
    resetForm: true
    }   ',
   'linkClass' =>".link",
   'submitStepClass' =>".submit_step",
   'back' => ":reset",
   'next' => ":submit",
   'textSubmit' => "Submit",
   'textNext' => "Next",
   'textBack' =>"Back",
   'remoteAjax' =>"undefined",
   'inAnimation' => "{opacity:'show'}",
   'outAnimation' => "{opacity:'hide'}",
   'inDuration' => 400,
   'outDuration' => 400,
   'easing' => "swing",
   'focusFirstInput' => "true",
   'disableInputFields' => "true",
   'disableUIStyles' => "false",
   'jsAfterStepShown'=> '
   /*   Available in data (data.steps ,data.settings etc):
    isBackNavigation - boolean
    settings - options object containing the options set for the wizard
    activatedSteps - list of activated steps (visited steps)
    isLastStep - boolean specifying whether the current step is a submit step
    isFirstStep - boolean
    previousStep - the id of the previously visited step
    currentStep - the id of the current step
    backButton
    nextButton
    steps - the steps of the wizard 
    firstStep - the id of the first step
   */
    $("#stepmessage").html("");
    $.each(data.activatedSteps, function(){
    $("#stepmessage").append(this+" - ");
   });
   var currentstepnumber = data.activatedSteps.length;                  
   $("#stepmessage").append("<br/>Step "+currentstepnumber+"/"+data.steps.length);',
   ));?>

Resources

Total 12 comments

#16535 report it
Tanguy at 2014/03/03 10:56am
updated extension

You can find an updated version here (3.0.7) :

https://github.com/tpruvot/SFormWizard

#14112 report it
lahiponeja at 2013/07/19 04:00pm
validationOptions Not Work

Hi, Guys. Anyone know how to make 'validationOptions' work, I use sformwizard, but the validations not works. Thanks a lot, for your colaboration.

My code is:

<?php /* @var $this RegistroController */ /* @var $model Registro */ /* @var $form CActiveForm */ error_reporting(E_ALL); ?>
<?php $form=$this->beginWidget('CActiveForm', array( 'id'=>'registro-form', 'enableAjaxValidation'=>true, //'enableClientValidation'=>true 'clientOptions'=>array( 'validateOnSubmit'=>true, ) )); ?>

Los datos con * son requeridos.

<?php echo $form->errorSummary($model); ?>
<?php echo $form->labelEx($model,'nombres_apellidos'); ?>
<?php echo $form->textField($model,'nombres_apellidos',array('id'=>'nombres_apellidos','size'=>60,'maxlength'=>100)); ?> <?php echo $form->error($model,'nombres_apellidos'); ?>
<?php echo $form->labelEx($model,'correo_institucional'); ?>
<?php echo $form->textField($model,'correo_institucional',array('id'=>'correo_institucional','size'=>60,'maxlength'=>100)); ?> <?php echo $form->error($model,'correo_institucional'); ?>
<?php echo $form->labelEx($model,'correo_alterno'); ?>
<?php echo $form->textField($model,'correo_alterno',array('id'=>'correo_alterno','size'=>60,'maxlength'=>100)); ?> <?php echo $form->error($model,'correo_alterno'); ?>
<?php echo $form->labelEx($model,'grupinv'); ?>
<?php echo $form->dropDownList($model,'grupinv',CHtml::listData(grupo::model()->findAll(array('order'=>'linea')), 'id', 'linea'),array('id'=>'grupinv','empty' => 'Seleccione'));?> <?php echo $form->error($model,'grupinv'); ?>
<?php echo $form->labelEx($model,'id'); ?>
<?php echo $form->textField($model,'id',array('size'=>18,'maxlength'=>18)); ?> <?php echo $form->error($model,'id'); ?>
<?php echo $form->labelEx($model,'telefono_contacto'); ?>
<?php echo $form->textField($model,'telefono_contacto',array('size'=>30,'maxlength'=>30)); ?> <?php echo $form->error($model,'telefono_contacto'); ?>
<?php echo $form->labelEx($model,'invprof'); ?> <?php $data =array('1'=>'SI','0'=>'NO'); echo $form->radioButtonList($model,'invprof', $data);?> <?php echo $form->error($model,'invprof'); ?>
<?php echo $form->labelEx($model,'fecini_pub'); ?> <?php if ($model->fecini_pub!='') { $model->fecini_pub=date('d-m-Y',strtotime($model->fecini_pub)); } $this->widget('zii.widgets.jui.CJuiDatePicker', array( 'model'=>$model, 'attribute'=>'fecini_pub', 'value'=>$model->fecini_pub, 'language' => 'es', 'htmlOptions' => array('readonly'=>"readonly"), 'options'=>array( 'autoSize'=>true, 'defaultDate'=>$model->fecini_pub, 'dateFormat'=>'dd-mm-yy', 'buttonImage'=>Yii::app()->baseUrl.'/images/calendar.png', 'buttonImageOnly'=>true, 'buttonText'=>'Fecha', 'selectOtherMonths'=>true, 'showAnim'=>'slide', 'showButtonPanel'=>true, 'showOn'=>'button', 'showOtherMonths'=>true, 'changeMonth' => 'true', 'changeYear' => 'true', ), )); ?> <?php echo $form->error($model,'fecini_pub'); ?>
<?php echo $form->labelEx($model,'concluido_inv'); ?> <?php $data =array('1'=>'SI','0'=>'NO'); echo $form->radioButtonList($model,'concluido_inv', $data);?> <?php echo $form->error($model,'concluido_inv'); ?>
<?php echo $form->labelEx($model,'fecfin_pub'); ?> <?php if ($model->fecfin_pub!='') { $model->fecfin_pub=date('d-m-Y',strtotime($model->fecfin_pub)); } $this->widget('zii.widgets.jui.CJuiDatePicker', array( 'model'=>$model, 'attribute'=>'fecfin_pub', 'value'=>$model->fecfin_pub, 'language' => 'es', 'htmlOptions' => array('readonly'=>"readonly"), 'options'=>array( 'autoSize'=>true, 'defaultDate'=>$model->fecfin_pub, 'dateFormat'=>'dd-mm-yy', 'buttonImage'=>Yii::app()->baseUrl.'/images/calendar.png', 'buttonImageOnly'=>true, 'buttonText'=>'Fecha', 'selectOtherMonths'=>true, 'showAnim'=>'slide', 'showButtonPanel'=>true, 'showOn'=>'button', 'showOtherMonths'=>true, 'changeMonth' => 'true', 'changeYear' => 'true', ), )); ?><?php echo $form->error($model,'fecfin_pub'); ?>
<?php echo $form->labelEx($model,'meses_inv'); ?> <?php echo $form->textField($model,'meses_inv'); ?> <?php echo $form->error($model,'meses_inv'); ?>
<?php echo $form->labelEx($model,'concluido_anapub'); ?> <?php $data =array('1'=>'SI','0'=>'NO'); echo $form->radioButtonList($model,'concluido_anapub', $data);?> <?php echo $form->error($model,'concluido_anapub'); ?>
<?php echo $form->labelEx($model,'text_noconc'); ?>
<?php echo $form->textArea($model,'text_noconc',array('rows'=>6, 'cols'=>80)); ?> <?php echo $form->error($model,'text_noconc'); ?>
<?php echo $form->labelEx($model,'estudpos_inclu'); ?> <?php $data =array('1'=>'SI','0'=>'NO'); echo $form->radioButtonList($model,'estudpos_inclu', $data);?> <?php echo $form->error($model,'estudpos_inclu'); ?>
<?php echo $form->labelEx($model,'prom_dedica'); ?> <?php $data =array('0'=>'0 Horas','1'=>'1 a 2 Horas','2'=>'1 a 2 Horas','3'=>'3 a 4 Horas','4'=>'5 a 6 Horas','5'=>'7 a 8 Horas','6'=>'9 a 10 Horas','7'=>'Más de 10 Horas'); echo $form->dropDownList($model,'prom_dedica',$data,array('empty' => 'Seleccione'));?> <?php echo $form->error($model,'prom_dedica'); ?>
<?php echo $form->labelEx($model,'estudpre_inclu'); ?> <?php $data =array('1'=>'SI','0'=>'NO'); echo $form->radioButtonList($model,'estudpre_inclu', $data);?> <?php echo $form->error($model,'estudpre_inclu'); ?>
<?php echo $form->labelEx($model,'titulo'); ?>
<?php echo $form->textArea($model,'titulo',array('rows'=>6, 'cols'=>100)); ?> <?php echo $form->error($model,'titulo'); ?>
<?php echo $form->labelEx($model,'pregunta'); ?>
<?php echo $form->textArea($model,'pregunta',array('rows'=>6, 'cols'=>100)); ?> <?php echo $form->error($model,'pregunta'); ?>
<?php echo $form->labelEx($model,'objetivo'); ?>
<?php echo $form->textArea($model,'objetivo',array('rows'=>6, 'cols'=>100)); ?> <?php echo $form->error($model,'objetivo'); ?>
<?php echo $form->labelEx($model,'tipoestudio'); ?>
<?php echo $form->textArea($model,'tipoestudio',array('rows'=>6, 'cols'=>100)); ?> <?php echo $form->error($model,'tipoestudio'); ?>
<?php echo $form->labelEx($model,'metodologia'); ?>
<?php echo $form->textArea($model,'metodologia',array('rows'=>6, 'cols'=>100)); ?> <?php echo $form->error($model,'metodologia'); ?>
<?php echo $form->labelEx($model,'resultados'); ?>
<?php echo $form->textArea($model,'resultados',array('rows'=>6, 'cols'=>100)); ?> <?php echo $form->error($model,'resultados'); ?>
<?php echo $form->labelEx($model,'aportes'); ?>
<?php echo $form->textArea($model,'aportes',array('rows'=>6, 'cols'=>100)); ?> <?php echo $form->error($model,'aportes'); ?>
<?php echo $form->labelEx($model,'adic_publicadoext'); ?> <?php $data =array('1'=>'SI','0'=>'NO'); echo $form->radioButtonList($model,'adic_publicadoext', $data);?> <?php echo $form->error($model,'adic_publicadoext'); ?>
<?php echo $form->labelEx($model,'relacionext'); ?>
<?php echo $form->textArea($model,'relacionext',array('rows'=>6, 'cols'=>100)); ?> <?php echo $form->error($model,'relacionext'); ?>
<?php echo $form->labelEx($model,'adic_publicadointer'); ?> <?php $data =array('1'=>'SI','0'=>'NO'); echo $form->radioButtonList($model,'adic_publicadointer', $data);?> <?php echo $form->error($model,'adic_publicadointer'); ?>
<?php echo $form->labelEx($model,'relacionint'); ?>
<?php echo $form->textArea($model,'relacionint',array('rows'=>6, 'cols'=>100)); ?> <?php echo $form->error($model,'relacionint'); ?>
<?php echo $form->labelEx($model,'pub_borrador'); ?> <?php $data =array('1'=>'SI','0'=>'NO'); echo $form->radioButtonList($model,'pub_borrador', $data);?> <?php echo $form->error($model,'pub_borrador'); ?>
<?php echo $form->labelEx($model,'pub_resultados'); ?> <?php $data =array('1'=>'SI','0'=>'NO'); echo $form->radioButtonList($model,'pub_resultados', $data);?> <?php echo $form->error($model,'pub_resultados'); ?>
<?php echo $form->labelEx($model,'pub_indexa'); ?> <?php $data =array('1'=>'SI','0'=>'NO'); echo $form->radioButtonList($model,'pub_indexa', $data);?> <?php echo $form->error($model,'pub_indexa'); ?>
<?php echo $form->labelEx($model,'nom_indexa'); ?> <?php echo $form->textField($model,'nom_indexa',array('size'=>60,'maxlength'=>80)); ?> <?php echo $form->error($model,'nom_indexa'); ?>
<?php echo CHtml::submitButton($model->isNewRecord ? 'Create' : 'Save'); ?>

<?php $this->endWidget(); ?> <?php $this->widget('ext.sformwizard.SFormWizard',array( 'selector'=>"#registro-form", 'historyEnabled' =>"true", 'validationEnabled' => "true", 'validationOptions' => '{ alert("el valor es baz"); rules: { "#grupinv" : "required", "#correo_alterno" : { required: "true", email: "true" } }, messages: { "#grupinv": "Please specify your country", "#correo_alterno": { required: "Please specify your email", email: "Correct format is name@domain.com" } } }', 'formPluginEnabled' => "true", 'formOptions' => '{ success: function(data){$("#stepmessage").fadeTo(500,1,function(){ $("#stepmessage").html(data); })}, beforeSubmit: function(data){ $("#data").html("data sent to the server: " + $.param(data)); }, dataType: "json", resetForm: true } ', 'linkClass' =>".link", 'submitStepClass' =>".submit_step", 'back' => ":reset", 'next' => ":submit", 'textSubmit' => "Guardar", 'textNext' => "Siguiente", 'textBack' =>"Atrás", 'remoteAjax' =>"undefined", 'inAnimation' => "{opacity:'show'}", 'outAnimation' => "{opacity:'hide'}", 'inDuration' => 400, 'outDuration' => 400, 'easing' => "swing", 'focusFirstInput' => "true", 'disableInputFields' => "true", 'disableUIStyles' => "true", 'jsAfterStepShown'=> ' /* Available in data (data.steps ,data.settings etc): isBackNavigation - boolean settings - options object containing the options set for the wizard activatedSteps - list of activated steps (visited steps) isLastStep - boolean specifying whether the current step is a submit step isFirstStep - boolean previousStep - the id of the previously visited step currentStep - the id of the current step backButton nextButton steps - the steps of the wizard firstStep - the id of the first step */ $("#stepmessage").html(""); $.each(data.activatedSteps, function(){ $("#stepmessage").append(this+" - "); $("#stepmessage").append($("#nombres_apellidos").val()+"data sent to the server: "+data.activatedSteps.length); }); var currentstepnumber = data.activatedSteps.length; $("#stepmessage").append("
Paso "+currentstepnumber+" de "+data.steps.length);', ));?>

#12113 report it
SteveD at 2013/02/27 03:15pm
Fix for submit_step problem

Out of the box, the submit_step class in a branch doesn't work as expected. It does work if you override the submitStepClass in the plugin definition statement to eliminate the leading period:

'submitStepClass'=>"submit_step",
#11170 report it
WebDevPT at 2012/12/21 11:01am
RE: Spatan

Hi, any progress? Post your message and your code on the forum thread so we can try to help you out. I'm using this but took me quite some time to start using it.

#11130 report it
spatan at 2012/12/19 06:17am
Not working

Hello, please ive been on this extension for 24 hours. Its not just working for me. i cant see the NEXT and PERVIOUS Buttons.

I followed thesame example on this page but yet, no luck.

#10305 report it
WebDevPT at 2012/10/18 10:09am
Dynamic Steps

Hi, I'm having some trouble implementing the example 15 for this extension Anyone can share with me how I can implement this? From the example I only see the script but i would like to know how i can use this inside my widget in a similar way that we can see in the given example on the extension page.

Thank you in advance.

#9711 report it
WebDevPT at 2012/09/05 06:49am
Validation Rules

"Hello, thanks for the plugin. I'm wondering if it is possible to merge someway, automatically, the rules explicited in the model and place them inside the validationOptions object of the plugin without explicitly rewrite everything by hand.

Any idea about it? Thanks!"

Having the same question, it would be great to use this feature. Any ideas on how to do this without typing each rule manually?

EDIT: also i'm trying to do this, and I can't view this validation message or the rule working.

'validationOptions' => '{
                                                    rules: {
                                                            field_a: "required",
                                                    },
                                                    messages: {
                                                            field_a: "required",
                                                    }
 
                                               }',
#9707 report it
bit0123 at 2012/09/05 03:33am
Thanks

I have got it. Again thanks a lot...

#9706 report it
bit0123 at 2012/09/05 03:21am
Back button is not shown in demo project

Thanks for the great and cool extension.

I need to shoe the back button but in the demo peoject the back button is disappear. How can i ad the back button in the form?

#9163 report it
SomethingWicked at 2012/07/25 06:55am
Automatic merge of model rules and validationOptions

Hello, thanks for the plugin. I'm wondering if it is possible to merge someway, automatically, the rules explicited in the model and place them inside the validationOptions object of the plugin without explicitly rewrite everything by hand.

Any idea about it? Thanks!

#9074 report it
WebDevPT at 2012/07/18 12:47am
looks great!

Good work.

Thank you

#9033 report it
bonnie at 2012/07/14 08:37pm
nice

thanks for this feature i have been looking for it.

Leave a comment

Please to leave your comment.

Create extension