Yii 1.1: multimodelform

Handling of multiple records and models in a form
88 followers

This extension allows to work with multiple records and different models in a edit form. It handles clientside cloning and removing input elements/fieldsets and serverside batchInsert/Update/Delete.

Creating forms with this functionality is a 'tricky' workaround in views and controllers. This widget should do the main part of the work for you. It can be useful for order/registration forms ...

You can find the latest release on Github

See:

'multimodelform' could be an updated version of my extension jqrelcopy, but because of the different approach jqrelcopy will stay as lightweight extension for other needs. If you don't have to work with models take a look at jqrelcopy.

Note

Not every form input element is supported.

You can use the a few basic CFormInputElement (text, textarea, dropdownlist, ...) and some widgets (CJuiDatePicker, see below) but at the moment

  • checkbox: you have to use a checkboxlist instead (see below and the demo.3.2)
  • Autocomplete ...

are not supported.

Features

  • Clientside Clone/Remove form elements / fieldsets with the jQuery plugin http://www.andresvidal.com/labs/relcopy.html
  • Simple handling of the submitted form data in the controllers create/update action
  • Simultanous editing multiple records and models (master/detail...)
  • Supports validation and error summary for each model/record
  • Autogenerating input form elements with the 'form builder' functionality of Yii

New since v2.0

  • tableView (= gridView)
  • Support for cloning widget form elements: CJuiDatePicker, extension datetimepicker

Imporant note when upgrading to v2.1

  • MultiModelForm::validate and MultiModelForm::save have now the same parameterlist, so you have to add 'deletedItems' as third parameter (see Usage Validate/Save)
MultiModelForm::save($model,$validatedItems,$deleteItems,$masterValues)

Requirements

  • Yii 1.1.6+

Usage

  • Extract the files under .../protected/extensions

  • Master/Detail example:

Assume you have two models 'group' (id, title) and 'member' (id, groupid, firstname,lastname,membersince). The id attribute is the autoincrement primary key.

  • Generate the models 'Group' and 'Member' with gii. For testing the error summary set the members firstname/lastname as required in the rules.

  • Generate the 'GroupController' and the group/views with gii. You don't need to create a 'MemberController' and the member views for this example.

  • Change the default actionUpdate of the GroupController to

public function actionUpdate($id)
{
    Yii::import('ext.multimodelform.MultiModelForm');
 
    $model=$this->loadModel($id); //the Group model
 
    $member = new Member;
    $validatedMembers = array(); //ensure an empty array
 
    if(isset($_POST['Group']))
    {
        $model->attributes=$_POST['Group'];
 
        //the value for the foreign key 'groupid'
        $masterValues = array ('groupid'=>$model->id);
 
        if( //Save the master model after saving valid members
            MultiModelForm::save($member,$validatedMembers,$deleteMembers,$masterValues) &&
            $model->save()
           )
                $this->redirect(array('view','id'=>$model->id));
    }
 
    $this->render('update',array(
        'model'=>$model,
        //submit the member and validatedItems to the widget in the edit form
        'member'=>$member,
        'validatedMembers' => $validatedMembers,
    ));
}
  • Change the code of actionCreate like this
public function actionCreate()
{
    Yii::import('ext.multimodelform.MultiModelForm');
 
    $model = new Group;
 
    $member = new Member;
    $validatedMembers = array();  //ensure an empty array
 
    if(isset($_POST['Group']))
    {
        $model->attributes=$_POST['Group'];
 
        if( //validate detail before saving the master
            MultiModelForm::validate($member,$validatedMembers,$deleteItems) &&
            $model->save()
           )
           {
             //the value for the foreign key 'groupid'
             $masterValues = array ('groupid'=>$model->id);
             if (MultiModelForm::save($member,$validatedMembers,$deleteMembers,$masterValues))
                $this->redirect(array('view','id'=>$model->id));
            }
    }
 
    $this->render('create',array(
        'model'=>$model,
        //submit the member and validatedItems to the widget in the edit form
        'member'=>$member,
        'validatedMembers' => $validatedMembers,
    ));
}
  • Change the renderPartial in views/group/create.php and update.php to transfer the parameters $member and $validatedMembers to the _form.php
echo $this->renderPartial('_form', array('model'=>$model,
                          'member'=>$member,'validatedMembers'=>$validatedMembers));
  • Change the generated code of the GroupController's form view (views/group/_form.php).
<div class="form wide">
 
<?php $form=$this->beginWidget('CActiveForm', array(
        'id'=>'group-form',
        'enableAjaxValidation'=>false,
)); ?>
 
<p class="note">Fields with <span class="required">*</span> are required.</p>
 
<?php
    //show errorsummary at the top for all models
    //build an array of all models to check
    echo $form->errorSummary(array_merge(array($model),$validatedMembers));
?>
 
<div class="row">
    <?php echo $form->labelEx($model,'title'); ?>
    <?php echo $form->textField($model,'title'); ?>
    <?php echo $form->error($model,'title'); ?>
</div>
 
<?php
 
// see http://www.yiiframework.com/doc/guide/1.1/en/form.table
// Note: Can be a route to a config file too,
//       or create a method 'getMultiModelForm()' in the member model
 
$memberFormConfig = array(
      'elements'=>array(
        'firstname'=>array(
            'type'=>'text',
            'maxlength'=>40,
        ),
        'lastname'=>array(
            'type'=>'text',
            'maxlength'=>40,
        ),
        'membersince'=>array(
            'type'=>'dropdownlist',
            //it is important to add an empty item because of new records
            'items'=>array(''=>'-',2009=>2009,2010=>2010,2011=>2011,),
        ),
    ));
 
$this->widget('ext.multimodelform.MultiModelForm',array(
        'id' => 'id_member', //the unique widget id
        'formConfig' => $memberFormConfig, //the form configuration array
        'model' => $member, //instance of the form model
 
        //if submitted not empty from the controller,
        //the form will be rendered with validation errors
        'validatedItems' => $validatedMembers,
 
        //array of member instances loaded from db
        'data' => $member->findAll('groupid=:groupId', array(':groupId'=>$model->id)),
    ));
?>
 
<div class="row buttons">
    <?php echo CHtml::submitButton($model->isNewRecord ? 'Create' : 'Save'); ?>
</div>
 
<?php $this->endWidget(); ?>
 
</div><!-- form -->

Usage Validate/Save

The behavior has changed in v2.1. In older versions 'save' always exceuted 'validate' internally. 'validate' means to recreate all items from the form data. So there was no chance to alter the attributes of the models in $validatedItems between calling 'validate' and 'save'.

No you can do something like this.

//validate formdata and populate $validatedItems/$deleteItems
if (MultiModelForm::validate($model,$validatedItems,$deleteItems,$masterValues)) 
{
 
 //... alter the model attributes of $validatedItems if you need ... 
 
 //will not execute internally validate again, because $validatedItems/$deleteItems are not empty
 MultiModelForm::save($model,$validatedItems,$deleteItems,$masterValues);
}

But you can still use 'save' without extra validate before. Validation will be internally done when $validatedItems/$deleteItems are empty.

$validatedItems=array();
 
if(isset($_POST['FORMDATA']) && MultiModelForm::save($model,$validatedItems,$deleteItems,$masterValues)) 
{
  //... validation and saving is ok ...
  //redirect ...
}
 
//No POST data or validation error on save 
$this->render ...

Usage tableView

Set the property 'tableView'=>true.

$this->widget('ext.multimodelform.MultiModelForm',array(
       ...
        'tableView' => true,
     //'tableFootCells' => array('footerCol1','footerCol2'...), //optional table footer
       ...
    ));

Usage widget form elements

Yii allows type='AWidget' as form element. So in your form config array you can use:

array( 
   'elements'=>array(
         ....
          'lastname'=>array(
            'type'=>'text',
            'maxlength'=>40,
            ),
 
            'dayofbirth'=>array(              
                'type'=>'zii.widgets.jui.CJuiDatePicker',
                'language'=>'de',
                'options'=>array(
                    'showAnim'=>'fold',
                ),
           ...                      
        )
    )

This however needs a javascript workaround on cloning the date element. We have to assign the CJuiDatePicker functionality to the cloned new element.

Since v2.0 there are the properties jsBeforeClone,jsAfterClone,jsBeforeNewId,jsAfterNewId available where javascript code can be implemented. Use 'this' as the current jQuery object.

For CJuiDatePicker and the extension extension datetimepicker there are predefined functions available, so it's easy to make cloning date fields work.

You have to assign the property 'jsAfterNewId' to the prepared code.

Assume your form definition elements are defined in the array $formConfig. 'afterNewIdDatePicker' reads the options from the specified element and adds the 'datepicker':

$this->widget('ext.multimodelform.MultiModelForm',array(
       ...
         // 'jsBeforeNewId' => "alert(this.attr('id'));", 
        'jsAfterNewId' => MultiModelForm::afterNewIdDatePicker($formConfig['elements']['dayofbirth']),
       ...
    ));

Now cloning of the field 'dayofbirth' should work.

Support for 'datetimepicker' is analog (afterNewIdDateTimePicker).

For other widgets you have to find out the correct javascript code on cloning. Please let me know if you have found a javascript code for other widgets.

Note: I couldn't get Autocomplete working. Maybe one of you has an idea (see afterNewIdAutoComplete in MultiModelForm.php).

Sortable fieldsets (since v3.0)

Set the property 'sortAttribute' to your db-field for sorting (should be an integer) if you want to order the items by drag/drop manually. Uses jQuery UI sortable, but works only when 'tableView' is false. See the demo.

$this->widget('ext.multimodelform.MultiModelForm',array(
       ...
        'sortAttribute' => 'position', //if assigned: sortable fieldsets is enabled
       ...
    ));

Property showAddItemOnError (since v3.0)

Regarding to requests and workarounds in the forum topic:

A user should not be able to add/clone items, when in error mode (model rules not passed successfully). Now you can set the property $showAddItemOnError to false to enable this behavior. See the demo.

Properties allowAddItem and allowRemoveItem (since v3.1)

For example, if you only want to allow an admin user to add new items or remove items, you can use these properties to display the addlink and the removelinks

$this->widget('ext.multimodelform.MultiModelForm',array(
       ...
       'allowAddItem' => Yii::app()->user->isAdmin(),
       'allowRemoveItem' => Yii::app()->user->hasRole('admin'),
       ...
    ));

Checkboxes

Unfortunatly the basic checkbox is not supported, because it's not so easy to handle (see the comments in the forum).

But if you need checkboxes, you can use the checkboxlist - see the demo.3.2 If you only need a single checkbox you can set the item-data to an array with one item.

In the view / formConfig:

$memberFormConfig = array(
          'elements'=>array(
 
             ...
            'flags'=>array(
              'type'=>'checkboxlist',
              'items'=>array('1'=>'Founder','2'=>'Developer','3'=>'Marketing'), //One single checkbox: array('1'=>'Founder')
              ),
        ));

In the model you have to convert array <-> string on saving/loading - see the Member model in the demo

/*
     * Convert the flags array to string
     */
    public function beforeSave()
    {
        if(parent::beforeSave())
        {
            if(!empty($this->flags) && is_array($this->flags))
                $this->flags = implode(',',$this->flags);
 
            return true;
        }
 
        return false;
    }
 
   /*
    * Convert the flags string to array
    */
   public function afterFind()
   {
       $this->flags = empty($this->flags) ? array() : explode(',',$this->flags);
   }

Bootstrap

Set the property 'bootstrapLayout'=true if you use Twitters Bootstrap CSS or one of the Yii bootstrap extensions.

The formelements/labels will be wrapped by 'control-group', 'controls', ... so that the multimodelform should be displayed correct.

property jsAfterCloneCallback

If you need to modify the cloned elements or execute js-actions after cloning, you can assign a js function(newElem,sourceElem) as callback.

  • newElem: the new cloned jquery object
  • sourceElem: the clone source object

The callback will be executed for all inputs of a record row.

Usage:

// a js function in your view
echo CHtml::script('function alertIds(newElem,sourceElem) { 
    alert(newElem.attr("id"));
    alert(sourceElem.attr("id"));}'
);
 
$this->widget('ext.multimodelform.MultiModelForm',array(
  ...
   'jsAfterCloneCallback'=>'alertIds',
  ...
));

Notes

  • Take a look at MultiModelForm.php for more options of the widget.

  • The widget never will render a form begin/end tag. So you have always to add $this->beginWidget('CActiveForm',...) ... $this->endWidget in the view.

  • The implementation of the class MultiModelEmbeddedForm needs review in upcoming Yii releases. In 1.1.6+ the only output of CActiveForm.init() and CActiveForm.run() is the form begin and end tag.

  • The extension should work for non activerecord models too: instances of CModel, CFormModel...

  • You can add more widgets for rendering other models in the form view. Take care to assign a unique widget id when adding more multimodelform widgets.

  • Use Yii::app()->controller->action->id or $model->scenario to generate different forms for your needs (readonly fields on update ...)

Ressources

Changelog

  • v5.0 better custom js handling please see comments in the code; don't forget to clear assets after update
    • new property 'removeOnClick' to exec js code on clicking the remove link
    • new property 'jsAfterCloneCallback' - usage: see documentation above
    • new property 'clearInputs' (= options['clearInputs'], default true) with bugfix on cloning values
    • new property 'jsRelCopy' to use your own modified jsrelcopy js-script (placed in assets folder)
  • v4.5
    • added support for composite pk
    • new property 'renderForm' allows a custom 'MultiModelRenderForm'
    • changed update behavior: loads the record from the db by findByPK before update (like default behavior of actionUpdate in a controller)
  • v4.1
    • Bugfix: rendering tableView with Bootstrap layout
  • v4.0

    • Bugfix: two remove columns in tableview when hideCopyTemplate=true. Many thanks to shoemaker. See this forum topic
    • Support for Twitters Bootstrap
    • New property 'addItemAsButton' to show a button 'Add item' instead of a link.
    • Minor bugfix in js-code
  • v3.3

    • Correct support for the options['limit'] property from relcopy.js. See property limitText.
  • v3.2
    • New property 'hideCopyTemplate' (default:true), means that the empty copyTemplate is not visible
    • New demo with CheckBoxList
  • v3.1
    • New: Added properties $allowAddItem and $allowRemoveItem
    • Bugfix: hidden fields in the Tableheader no more displayed
    • Bugfix: Strings as elements formconfig (htmlttags,CFormStringElement) have not been rendered
  • v3.0

    • New: Added sortable feature for fieldsets (not in table view)
    • New: Property $showAddItemOnError=true; Show 'Add item' link and empty item in errormode
    • New: Demo with sortable fieldsets
    • Bugfixes: visible/hidden fields
  • v2.2.1 Bugfix: Array elements need extra 'allEmpty' check 

  • v2.2
    • Support for array elements (checkboxlist, radiolist) in form config These elements didn't work on creating only on update
  • v2.1.1
    • Bugfix - Labels of hidden elements have been rendered
  • v2.1
    • Bugfix - tableView: Hidden input have been rendered into a cell
    • Changed parameters and handling of MultiModelForm::save
  • v2.0.1 Bugfix: Tableheader displayed hidden fields too. Better internal handling of labels, now supports required '*'
  • v2.0 Added 'tableView' and support for cloning date/time widgets
  • v1.0.2 Bugfix: Detailrecord was created twice on creating master
  • v1.0.1 Bugfix 'Undefined Index','Undefined variable' when error_reporting(E_ALL) is set

Total 20 comments

#16684 report it
ajobegs at 2014/03/19 02:53am
3 member in one Group

is it possible to build 3 member in one form??

#16203 report it
skworden at 2014/01/27 10:32pm
Template?

Is there anyway to use a template for the fields? I want to wrap them inside multiple divs and span classes. i.e. like this

<div class="col-md-4">
        <div class="input-icon">
                <label class="control-label"><?php echo $form->labelEx($model,'state'); ?></label>
                <i class="fa fa-home"></i>
                <?php echo $form->dropDownList($model, 'state', CHtml::listData( States::model()->findAll(),
                'id', 'state'),array('class'=>'form-control', 'prompt' => 'Select a State','maxlength'=>2, 'style'=>'padding-left:30px;')); ?>
        </div>
        <span class="help-block">
                <?php echo $form->error($model,'state'); ?>
        </span>
</div>

Also how do you get the id for the item? i want to get it to show related data on the form.

#16202 report it
skworden at 2014/01/27 10:28pm
FYI

First of all great extension. It works great and saved me tons of time.

In action update / create with a drop down it kept inserting a new row into my database even though my items were not set to add them in the form on my dropdown. i had to change your example for action update/ create to check if my field had an input.

public function actionUpdate($id)
    {
        Yii::import('ext.multimodelform.MultiModelForm');
 
        $model=$this->loadModel($id); //the Group model
 
        $physician = new PatientsPhysician;
        $validatedPatientPhysician = array(); //ensure an empty array
 
       if(isset($_POST['Patients']))
        {
            $model->attributes=$_POST['Patients'];
 
            //the value for the foreign key 'physician_id'
            $masterValues = array ('patient_id'=>$model->id);
 
                /* check to see if field is set on dropdown*/
            if(isset($_POST['PatientsPhysician']['physician_id']))
            {
                if( //Save the master model after saving valid physicians
                    MultiModelForm::save($physician,$validatedPatientPhysician,$deleteMembers,$masterValues) &&
                    $model->save()
                   )
                $this->redirect(array('view','id'=>$model->id));
            }
            if($model->save()){
                $this->redirect(array('view','id'=>$model->id));
            }
        }
 
        $this->render('update',array(
        'model'=>$model,
        //submit the physician and validatedItems to the widget in the edit form
        'physician'=>$physician,
        'validatedMembers' => $validatedPatientPhysician,
        ));
    }

and my view is as follows

<?php
// see http://www.yiiframework.com/doc/guide/1.1/en/form.table
// Note: Can be a route to a config file too,
//       or create a method 'getMultiModelForm()' in the member model
 
$paitentFormConfig = array(
      'elements'=>array(
 
        'physician_id'=>array(
            'type'=>'dropdownlist',
            'empty'=>'  ',
            //it is important to add an empty item because of new records
            'items'=>CHtml::listData( Physician::model()->findAll(), 'id', 'first_name'),
        )),
);
 
$this->widget('ext.multimodelform.MultiModelForm',array(
        'id' => 'id_physicians', //the unique widget id
        'formConfig' => $paitentFormConfig, //the form configuration array
        'model' => $physician, //instance of the form model
 
        //if submitted not empty from the controller,
        //the form will be rendered with validation errors
        'validatedItems' => $validatedMembers,
        'tableView' => false, //sortable will not work
            'fieldsetWrapper' => array('tag' => 'div', 'htmlOptions' => array('class' => 'col-md-3')),
            'removeLinkWrapper' => array('tag' => 'div', 'htmlOptions' => array('class'=>'red', 'style'=>' color: ffffff;')),
            'removeHtmlOptions'=>array('class'=>'portfolio-btn', 'style'=>' color: ffffff;'),
            'addItemText' => 'Add Physician',
            'removeText' => 'Remove Physician', 
            'removeConfirm' => 'Are you sure you want to remove this physician?', 
        //array of member instances loaded from d
        'data' => $physician->findAll('patient_id=:patientId', array(':patientId'=>$model->id)),
    ));
?>
#15857 report it
Joblo at 2013/12/23 03:43am
display errors

An input error (generated by the model rules) should be displayed near the fields too, not only in errorSummary.

Did you check the demo, leaving lastname of the member blank (is required in model rules)?

#15855 report it
mem at 2013/12/22 06:18pm
Validation near fields

If instead of using:

echo $form->errorSummary(array_merge(array($model),$validatedMembers));

We wish to display the error messages near each field on the form. Is this possible to accomplish? Lets say we have a form with Team and Members, and for each member, that a user can add or remove via ajax, if they are filled in and present, we wish to validate them and display the error near those form fields. Is this possible?

Thanks.

#15225 report it
bvpk at 2013/10/19 03:56am
problem with delete.

first of all thank to your work. i have one problem when delete group , it will provide problem for me.

#15169 report it
nat3863 at 2013/10/14 11:51am
ID number of cloned elements.

Hi Joblo. Thanks. But I would like to specifically get the ID number for a specific element. For example, if I have one field that which its id called Text_field, I would to get the number of the ID after it has been cloned. e.g.:

Text_field
Text_field1
Text_field2
#15163 report it
Joblo at 2013/10/14 05:24am
Id of cloned elements

You can register a js-function 'jsAfterCloneCallback' since v5.0.

See the example for the property jsAfterCloneCallback in the documentation above.

#15162 report it
nat3863 at 2013/10/14 04:04am
Getting ID number of cloned elements.

Hi, any idea how I can get id number of cloned elements? Thank you!

#14589 report it
ajobegs at 2013/08/26 02:51am
Many members

Hello All. I have the database

==== Class Group ====
     id
     name
 
     ==== Member1 ====
     id
     group_id
     Teacher
 
   ==== Member2 ====
     id
     group_id
     Student
 
   ==== Member3 ====
     id
     group_id
     Course

My Question is how to create more than 1 member instance.

for example :

public function actionCreate()
  {
    $model=new Group;
    $member1=new Member1;
     $member2=new Member2;
     $member3=new Member3;
     $member4=new Member4;
     ....//and other more than 10 members
#14566 report it
fart at 2013/08/23 08:10am
Update a field

All this I ask is because I try to update a field in the same row (by js) once enter a value in another and I do not know how to do if the Id of the fields are duplicated from one row to another when you delete a row except the last. Any suggestions?

Anyway, thank you very much JoBlo, for this great extension

#14555 report it
Joblo at 2013/08/22 08:50am
removeLink

Your wishes are very specific, I don't know how to implement this generally.

The best is, you create your own MultiModelForm widget, that inherits MultiModelForm and override the methods you need. Search for the getRemoveLink method in your code to see where/when the removelink is rendered.

#14553 report it
fart at 2013/08/22 08:38am
Deleting a row

Hello, Can I restrict the deletion to the last row inserted ? Only the last one.

#14544 report it
fart at 2013/08/22 04:28am
Deleting a row

Thanks JoBlo. I tried

'removeHtmlOptions' => array ('onMouseUp' => 'updateField ()')

but the event onMouseDown onMouseUp and onclick run before, which I can not update the field to delete the row.

I have another problem. When I delete a row that is not the last, I duplicated the "id" of all fields of the last row. It could prevent the counter ids of the flas fields are decremented to delete a row? Use the id to update another field in the row in the onChange event of one of them.

#14532 report it
Joblo at 2013/08/21 03:41am
js on deleting rows

The 'onclick' event of the removeLink is generated by the extension, but the removeHtmlOptions used as htmloptions for the remove-link is a public property.

Maybe you can execute js-code after deleting by setting the 'onmouseup' in the removeHtmlOptions.

#14511 report it
fart at 2013/08/19 07:27am
After deleting a row

Hi, please.... How can I execute javascript code after deleting a row ?

Thanks a lot

#14170 report it
fart at 2013/07/24 09:43am
Re: CJuiAutoComplete does not work well

Hello Ilya, Thank you very, very. very much .... It works perfect now !!!!!!!!

#14169 report it
__construct() at 2013/07/24 09:32am
Re: CJuiAutoComplete does not work well

Hello, fart :)

This error happens because you are forgot to set 'jsAfterNewId' in your multimodelform widget.

Add string like that into your widget configuration array inside "_form.php", and everything will work fine.

'jsAfterNewId' => MultiModelForm::afterNewIdAutoComplete( $detalleFormConfig['elements']['descripcion']),

Regards, Ilya.

#14168 report it
fart at 2013/07/24 08:49am
CJuiAutoComplete does not work well

CJuiAutoComplete + multimodelform: It works fine for the first row, but the second does not show autocomplete support What's wrong?

this is my _form.php

<?php
/* @var $this PedidoController */
/* @var $model Pedido */
/* @var $form CActiveForm */
?>
 
<div class="form wide">
 
<?php $form=$this->beginWidget('CActiveForm', array(
    'id'=>'pedido-form',
    'enableAjaxValidation'=>false,
)); ?>
 
    <p class="note">Los campos marcados con <span class="required">*</span> son obligatorios.</p>
 
    <?php echo $form->errorSummary(array_merge(array($model),$validatedDetalle)); ?>
 
    <div class="row">
        <?php echo $form->labelEx($model,'numeroPedido'); ?>
        <?php echo $form->textField($model,'numeroPedido',array('disabled' => true,'style'=>'width:80px;color:green;')); ?> 
        <?php echo $form->error($model,'numeroPedido'); ?>
    </div>
 
    <div class="row">
        <?php   
            $detalleFormConfig = array(
                'elements'=>array(
 
                'descripcion'=>array(
                    'type'=>'zii.widgets.jui.CJuiAutoComplete',
                        'name'=>'descripcion',
                        'value'=>$detalle->descripcion,
                        'visible' => true,
                        'source'=>$this->createUrl('autocompletedescripcion'),
                        'options'=>array(
                            'showAnim'=>'fold',
                        ),
                ),
 
                'precio'=>array(
                    'type'=>'text',
                    'size'=>'10',
                    'maxlength'=>10,
                    'id'=>'precio',
                    'STYLE'=>'text-align:right; width:60px',
                ),
            ));
 
 
            $this->widget('ext.multimodelform.MultiModelForm',array(
                'id' => 'id_detalle', //the unique widget id
                'formConfig' => $detalleFormConfig, //the form configuration array
                'model' => $detalle, //instance of the form model
                'validatedItems' => $validatedDetalle,
                'data' => empty($validatedItems) ? $detalle->findAll('pedido_id=:idPedido', array(':idPedido'=>$model->id)): null,
                'showAddItemOnError' => false,
                'tableView' => true, //sortable will not work
                'fieldsetWrapper' => array('tag' => 'div', 'htmlOptions' => array('class' => 'view','style'=>'position:relative;background:#EFEFEF;')),
                'removeLinkWrapper' => array('tag' => 'div', 'htmlOptions' => array('style'=>'position:absolute; top:1em; right:1em;')),
                'addItemText' => 'Agregar',
                'removeText' => 'Eliminar', 
                'removeConfirm' => '¿ Eliminar el artículo seleccionado ?', 
 
            ));
        ?>
    </div>
 
    <div class="row buttons">
        <?php echo CHtml::submitButton($model->isNewRecord ? 'Guardar' : 'Actualizar'); ?>
    </div>
 
 
<?php $this->endWidget(); ?>
</div><!-- form -->

My MultiModelForm.php ...

/**
     * Support for CJuiAutoComplete. 
     *
     * @contributor Smirnov Ilya php1602agregator[at]gmail.com
     * @param array $element
     * @return string
     */
    public static function afterNewIdAutoComplete($element)
    {
        $options = isset($element['options']) ? $element['options'] : array();
        if (isset($element['sourceUrl']))
            $options['source'] = CHtml::normalizeUrl($element['sourceUrl']);
        else
            $options['source'] = $element['source'];
 
        $jsOptions = CJavaScript::encode($options);
 
        return "if ( this.hasClass('ui-autocomplete-input') )
            {
                var mmfAutoCompleteParent = this.parent();
                // cloning autocomplete element (without data and events)
                var mmfAutoCompleteClone  = this.clone();
 
                // removing old autocomplete element
                mmfAutoCompleteParent.empty();
                // re-init autocomplete with default options
                mmfAutoCompleteClone.autocomplete({$jsOptions});
 
                // inserting new autocomplete
                mmfAutoCompleteParent.append(mmfAutoCompleteClone);
            }";
    }

Thanks so much !!!

#14069 report it
Joblo at 2013/07/17 03:08am
github

Yes, this is the correct github link: https://github.com/yii-joblo/multimodelform

Leave a comment

Please to leave your comment.

Create extension