2

I have two tables in database profile_fields and profile_fields_values.

Table profile_fields has columns

  • id
  • fieldname
  • fieldtitle
  • fieldtype
  • orderby
  • required
  • published

Table profile_field_values has columns

  • id
  • field_id
  • user_id
  • field_value

Here I have to create a dynamic profile management.

How do I show dynamic forms in Yii?

Stephen Ostermiller
  • 23,933
  • 14
  • 88
  • 109

2 Answers2

0

You need to use Form Builder, it has plenty of example how to construct your form using an array. It also supports sub-forms. Just follow the examples from the linked tutorial, content it's to long to be referenced here.

Update:

class LoginForm extends CFormModel
{
    public $username;
    public $password;
}

$form = new LoginForm();
$form->validatorList->add(
    CValidator::createValidator('required', $form, 'username, password')
);

or another example:

class SomeModel
{
 public $orders;
 public function rules()
 {
  return array(
   array('orders', 'validateOrders'),
  );
 }

 public function validateOrders($attribute, $params)
 {
  foreach($this->orders as $order)
   if (empty($order)) {
    $this->addError('orders', 'There is an empty order');
    break;
   }
 }
}

A more broader example is on forum.

Pentium10
  • 204,586
  • 122
  • 423
  • 502
  • what stops you to build the array for validation the same way you build the form. Dynamic model can be achieved with an intelligent model, you can handle there properties, even auto generate custom validation methods if you have to extend that further. – Pentium10 Feb 05 '14 at 07:20
  • May u please explain me about intelligent model or give me some links ? – Gaurav Parashar Feb 05 '14 at 12:34
  • Thank you very much but I am a new to yii so how I will I manage all my type of fields like checkbox ,text ,file in model for validation and how I will show them in dynamic forms can you tell me the MODEL VIEW AND CONTROLLER for dynamic forms according to above table and once again thanks dear – Gaurav Parashar Feb 05 '14 at 18:27
0
I am trying to build this dynamic profile management let me know my approach is my approach is right?

firstly i have created a input form(_form) where user can input fieldtype,fieldname,fieldtitle and field default value and etc which can be save in database table (profile_fields).In this fieldtype is bydefault set and user choose it from dropdownlist As like in the below form.

<?php
/* @var $this ProfileManagerController */
/* @var $model ProfileFields */
/* @var $form CActiveForm */

?>

<div class="form">

<?php $form=$this->beginWidget('CActiveForm', array(
    'id'=>'profile-fields-form',
    'enableAjaxValidation'=>false,
)); ?>

    <p class="note">Fields with <span class="required">*</span> are required.</p>
    <?php echo $form->errorSummary($model); ?>

    <div class="row">
        <?php echo $form->labelEx($model,'location'); ?>
        <?php echo $form->dropDownList($model,'location',CHtml::listData(Countries::model()->findAll('',array('orderby' => 'countryName ASC')),'countryCode','countryName'), array('empty' => array("*" => 'For All Countries'))); ?>
        <?php echo $form->error($model,'location'); ?>
    </div>
    <div class="row">
        <?php echo $form->labelEx($model,'profile_type'); ?>
        <?php echo $form->dropDownList($model,'profile_type',Yii::app()->params['userRoles'], array('empty' => array("*" => 'For All users')), array($model->profile_type)); ?>
        <?php //echo $form->dropDownList($model, 'profile_type', Yii::app()->params['userRoles'], array($model->profile_type)); ?>
        <?php echo $form->error($model,'profile_type'); ?>
    </div>
    <div class="row">
        <?php echo $form->labelEx($model,'section'); ?>
        <?php echo $form->dropDownList($model,'section',array('profile'=>'profileSection','basicdetails'=>'BasicDetails','contactdetails'=>'ContactDetails','imagedetails'=>'ImageDetails','clientdetails'=>'ClientDetails','tagdetails'=>'TagDetails','otherdetails'=>'OtherDetails','alldetails'=>'AllDetails')); ?>
        <?php echo $form->error($model,'section'); ?>
    </div>
    <div class="row">
        <?php echo $form->labelEx($model,'field_name'); ?>
        <?php echo $form->textField($model,'field_name',array('size'=>60,'maxlength'=>255)); ?>
        <?php echo $form->error($model,'field_name'); ?>
    </div>
    <div class="row">
        <?php echo $form->labelEx($model,'field_title'); ?>
        <?php echo $form->textField($model,'field_title',array('size'=>60,'maxlength'=>255)); ?>
        <?php echo $form->error($model,'field_title'); ?>
    </div>
    <div class="row">
        <?php echo $form->labelEx($model,'field_type'); ?>
        <?php echo $form->dropDownList($model,'field_type',array('text' => 'Text','date' => 'Date','email' => 'Email', 'radio' => 'Radio','multiselect' => 'Multi Select Dropdown List','file'=>'File','checkbox'=>'CheckBox','hidden'=>'Hidden','select'=>'Dropdownlist','password'=>'Password','checkboxlist'=>'Checkboxlist','radiolist'=>'Radiolist','textarea'=>'TextArea'),array('options' => array($model->field_type => array('selected' => true)))); ?>
        <?php echo $form->error($model,'field_type'); ?>
    </div>
    <div class="row">
        <?php echo $form->labelEx($model,'field_default_value'); ?>
        <?php echo $form->textArea($model,'field_default_value',array('rows'=>6, 'cols'=>50)); ?>
        <?php echo $form->error($model,'field_default_value'); ?>
    </div>
    <div class="row">
        <?php echo $form->labelEx($model,'required'); ?>
          <?php echo $form->dropDownList($model, 'required', array('1' => 'Yes', '0' => 'No')); ?>
        <?php echo $form->error($model,'required'); ?>
    </div>
    <div class="row">
        <?php echo $form->labelEx($model,'published'); ?>
          <?php echo $form->dropDownList($model, 'published', array('1' => 'Yes', '0' => 'No')); ?>
        <?php echo $form->error($model,'published'); ?>
    </div>
    <div class="row">
        <?php echo $form->labelEx($model,'order_by'); ?>
        <?php echo $form->textField($model,'order_by'); ?>
        <?php echo $form->error($model,'order_by'); ?>
    </div>
    <div class="row buttons">
        <?php echo CHtml::submitButton($model->isNewRecord ? 'Create' : 'Save'); ?>
    </div>

<?php $this->endWidget(); ?>

</div><!-- form -->
secondly I have created a view index file which will show dynamically what type of fieldstypes and fieldsname and field title are set by the user in profile_field table and call the extension created by me and then another  user can input accordingly .and these values are save in profile_field_values table .
----------index file---------------


<div class="form">

    <?php
    $form = $this->beginWidget('CActiveForm', array(
        'id' => 'completeProfile-form',
        'htmlOptions' => array('enctype' => 'multipart/form-data'),
        'enableAjaxValidation' => false,
        'clientOptions' => array('validataOnSubmit' => true),
        'enableClientValidation' => true,        
    ));
    ?>
    <?php
    if (!empty($field_data)) {
        foreach ($field_data as $field) { 
            $selectedOptions = '';
            $def_value='';
            $field_name = $field->field_name; // required field
            $field_type = $field->field_type; // required field
            $field_id = $field->id; // required field

            //for validation 
            $req = $field->required == 1 ? 'required' : ''; // required if using validation
            $email = $field->field_type == 'email' ? 'email' : ''; // required if using validation
            $password = $field->field_type == 'password' ? 'password' : ''; // required if using validation
            $class = array($req, $email, $password); // class must be array type, if no class found, send empty array
            //values present in  ProfileFieldsValues to populate
            $value = ProfileFieldsValues::model()->findByAttributes(array('user_id' => Yii::app()->user->id, 'field_id' => $field->id));
            // set html options
            $htmlOptions = array();
            $htmlOptions['class'] = implode(" ", $class);
            $htmlOptions['value'] = $value ? $value->field_value : '';
            // field array - Must SET
            $fieldArray = array();
            $fieldArray['model'] = $field;
            $fieldArray['form'] = $form;
            $fieldArray['field_type'] = $field_type;
            $fieldArray['field_name'] = $field_name;
            $fieldArray['field_id'] = $field_id;
            $fieldArray['default_value'] = $value ? $value->field_value : $field->field_default_value;

            //If input type field is dropdowlist for selecttion
            if($field_type == 'select' ){
                if(!empty($field->field_default_value)){
                    $my_string = preg_replace(array('/\n/'), '#PH#', $field->field_default_value );
                    $my_array = explode('#PH#', $my_string);
                    foreach($my_array as $my_arr){
                            $def=explode('|',$my_arr);
                            $def_value[$def[0]]=$def[1];
                    }
                     $fieldArray['select_box_array']=$def_value;
                }else{
                     $fieldArray['select_box_array'] =$country;
                }
                $htmlOptions['prompt'] = 'SELECT ANY';
                $value ? $htmlOptions['options']=array($value->field_value=>array('selected'=>'true')): $htmlOptions['prompt'] = 'SELECT ANY';
            }
            //if input type field is multiple select dropdownlist
            if( $field_type == 'multiselect'){
                if(!empty($field->field_default_value)){
                    $my_string = preg_replace(array('/\n/'), '#PH#', $field->field_default_value );
                    $my_array = explode('#PH#', $my_string);
                    foreach($my_array as $my_arr){
                    $def=explode('|',$my_arr);
                    $def_value[$def[0]]=$def[1];
                    }
                    $fieldArray['select_box_array']=$def_value;
                }else{
                    $fieldArray['select_box_array'] =$country;
                }
                $htmlOptions['prompt'] = 'SELECT Multiple';
                if(!empty($value)){
                $field_valu= explode(',',$value->field_value); 
                foreach($field_valu as $eachValue){
                    $selectedOptions[$eachValue] = array('selected'=>'selected');
                 }
                $htmlOptions['options']= $selectedOptions;
                }

            }
            // if input type field is radio button
            if ($field_type == 'radiolist') {
                $fl = ProfileFieldsValues::model()->findByAttributes(array('field_id' => $field->id, 'user_id' => Yii::app()->user->id));                
                if(!empty($field->field_default_value)){
                $my_string = preg_replace(array('/\n/'), '#PH#', $field->field_default_value );
                $my_array = explode('#PH#', $my_string);
                foreach($my_array as $my_arr){
                    $def=explode('|',$my_arr);
                    $def_value[$def[0]]=$def[1];
                }
                 $fieldArray['radio_box_array']=$def_value;
                }else{
                 $fieldArray['radio_box_array'] =array('hello','bye');
                }

                $value = $fl ? $fl->field_value : 0;
                $htmlOptions = array('labelOptions' => array('style' => 'display:inline'), 'separator' => ' ','value' => $value);
            }
            //if input type field is checkbox list
            if ($field_type == 'checkboxlist') {
                $fl = ProfileFieldsValues::model()->findByAttributes(array('field_id' => $field->id, 'user_id' => Yii::app()->user->id));
                if(!empty($field->field_default_value)){
                    $my_string = preg_replace(array('/\n/'), '#PH#', $field->field_default_value );
                    $my_array = explode('#PH#', $my_string);
                    foreach($my_array as $my_arr){
                        $def=explode('|',$my_arr);
                        $def_value[$def[0]]=$def[1];
                    }
                    $fieldArray['check_box_array']=$def_value;
                }else{
                    $fieldArray['check_box_array'] =array('hello','bye');
                }

                $value = $fl ? (array)explode(",",$fl->field_value) : array(0);                                
                $htmlOptions = array('labelOptions' => array('style' => 'display:inline'), 'separator' => ' ','value' => $value );
            }
            //if input type field is file
            if ($field_type == 'file') {
                $files = ProfileFieldsValues::model()->findByAttributes(array('field_id' => $field->id, 'user_id' => Yii::app()->user->id));
                if(isset($files->field_value)){
                    echo CHtml::image(Yii::app()->request->baseUrl . '/images/user_images/' .$files->field_value, 'Image', array('class' => 'img-polaroid', 'width' => 200)); 
                }
            }
            $fieldArray['htmlOptions'] = $htmlOptions;
                if ($field->published == '1') { 
                        if($field->field_type == 'checkbox' || $field->field_type == 'radio' ){ ?>
                        <div class="row">   
                            <?php $this->widget('ext.dynamicFields.EDynamicFields', $fieldArray); ?>
                            <?php echo $field->field_title; ?>
                            <?php echo $form->error($field, $field->field_title); ?>
                        </div>
                        <?php }else{ ?>
                        <div class="row">   
                        <?php echo $form->labelEx($field, $field->field_title); ?>
                        <?php $this->widget('ext.dynamicFields.EDynamicFields', $fieldArray); ?>
                        <?php echo $form->error($field, $field->field_title); ?>
                        </div>
                        <?php } ?>
                <?php } ?>
            <?php } ?>
            <div class="row buttons">
                <?php echo CHtml::submitButton('Submit'); ?>
            </div>

        <?php

    }
     $this->endWidget();
    ?>

</div><!-- form -->
<?php Yii::app()->clientScript->registerScriptFile(Yii::app()->getBaseUrl(true) . '/js/jquery.validate.js'); ?>
<script type="text/javascript">

    $("#completeProfile-form").validate({
    });
</script>


I have created a extension for various input type fields like
1.text
2.email textbox
3.hidden input type field
4.textarea
5.dropdownlist 
6. multiple select dropdownlist
7.password textfield            
8.file
9.radiolist
10.radio button
11 checkbox
12checkboxlist
13 date field             
   <?php

/**
 * Description of EDynamicFields
 * It will show dynamic fields
 *
 * @author Gaurav Parashar
 */
class EDynamicFields extends CWidget {

    public $field_type;
    public $field_name;
    public $field_id;
    public $default_value;
    public $select_box_array = array();
    public $radio_box_array = array();
    public $check_box_array = array();
    public $htmlOptions = array();
    public $model;
    public $form;
    public $select;

    public function run() {
        switch ($this->field_type) {
            case 'text':
                echo $this->form->textField($this->model, "field_name[$this->field_type][$this->field_id]", $this->htmlOptions);
            break;
            case 'email':
                echo $this->form->textField($this->model, "field_name[$this->field_type][$this->field_id]", $this->htmlOptions);
            break;
            case 'hidden':
                echo $this->form->hiddenField($this->model, "field_name[$this->field_type][$this->field_id]", $this->default_value);
            break;
            case 'textarea':
                echo $this->form->textArea($this->model, "field_name[$this->field_type][$this->field_id]", $this->htmlOptions);
            break;
            case 'select':
                echo $this->form->dropDownList($this->model, "field_name[$this->field_type][$this->field_id]", $this->select_box_array, $this->htmlOptions);
            break;
            case 'password':
                echo $form->passwordField($model,'password',$this->htmlOptions);
                break;
            case 'multiselect':
                $newarr = array_merge($this->htmlOptions, array('multiple' => 'multiple'));
                echo $this->form->dropDownList($this->model, "field_name[$this->field_type][$this->field_id]", $this->select_box_array, $newarr);
            break;
            case 'file':
                echo $this->form->fileField($this->model, "field_name[$this->field_type][$this->field_id]" ,$this->htmlOptions);
            break;
            case 'radio':
                echo $this->form->radioButton($this->model, "field_name[$this->field_type][$this->field_id]", $this->htmlOptions);
            break;
            case 'radiolist':
                echo CHtml::radioButtonList("ProfileFields[field_name][$this->field_type][$this->field_id]",$this->htmlOptions['value'],$this->radio_box_array,$this->htmlOptions);
            break;
            case 'checkbox':
                echo $this->form->checkBox($this->model, "field_name[$this->field_type][$this->field_id]", $this->htmlOptions);
            break;
            case 'date':
                 $this->widget('zii.widgets.jui.CJuiDatePicker', array(
                                'attribute' => "field_name[$this->field_type][$this->field_id]",
                                'model' => $this->model,
                                'htmlOptions'=>array(
                                'class'=>'required',
                                ),    
                                'options' => array(
                                        'dateFormat' => 'yy-mm-dd',
                                        'maxDate' => 'new Date()', // One month ahead
                                        //'minDate' => '-50y', // Today
                                        'changeMonth' => true,
                                        'changeYear' => true,
                                        'yearRange'=>'2000:2099',
                                        'minDate' => '2000-01-01',      // minimum date
                                        'maxDate' => '2099-12-31',

                                )
                ));
            break;
            case 'checkboxlist':
                    echo CHtml::checkBoxList("ProfileFields[field_name][$this->field_type][$this->field_id]",$this->htmlOptions['value'],$this->check_box_array,$this->htmlOptions);
            break;
        }
    }

}