[EXTENSION] multimodelform/jqrelcopy

The addlink is rendered by MultiModelRenderForm.getAddLink().

Take a look at the html source and create a css to move this item around.

I want to ask something

I have two input, the first is param_type, and the second is param_value …

I want to make when I set the param type = 0, then param_value = textField

if param type = 1, then param_value = dropDown …

is it possible to do this? :)

Hello,

How I can do to add items to the calculations made ​​in the fields of the parent table.

Thanks,

Mr D: Sorry, I don’t see a change for this :frowning:

IRCSASW:

Should be possible with js/jQuery.

Try to set the ‘onChange’ of your inputs and add js-code to the property ‘jsAfterClone’ of the multimodelform.

I would try to add code direct in the js-script ‘jquery.relcopy.yii.1.0.js’ first and afterwards when it works put the code outside to the ‘jsAfterClone’.

You both should know:

At the clientside multimodelform does only clone a collection of form elements

and increments the id of each element by an integer so that the form values are posted as an array on submit.

Nothing more happens.

So if you need complex features you have to work with javascript before/after cloning the elements and you have to understand the code from ‘jquery.relcopy.yii.1.0.js’ how the cloning works.

Thanks Joblo, I’ll work on this. Greetings.

LiuXuan: Comment IDENTITY_INSERT issue when adding new member

multimodelform renders all db-fields into the form. If elements are not configured in the formConfig, the fields are rendered as type=‘hidden’.

This is necessary because there is no ‘loadmodel’ before update, so all record values has to be submitted from the form.

So an empty PK autoinc fieldvalue is submitted too.

But on save, the extension uses the Yii $model->save() method.

AFAIK, this method handles the ‘autoincrement’, so the autoinc attribute should not be submitted to the db.

Otherwise you can use the models ‘beforeSave’ to remove the autoinc attribute or set it to NULL.

Maybe this is an issue of the difference of an empty fieldvalue ‘’ or NULL.

multimodelform should not output the fields which are not configured as elements in the formconfig.

But there is an issue so the labels of hidden fields are rendered in the table header too.

You can fix this in line 832 of MultiModelForm.php version 2.2.1




public function renderTableHeader()

	{

		$cells = '';


		foreach($this->getElements() as $element)

			if ($element->visible  && !$element->type == 'hidden') //<--- add check for hidden type too

			{

				$text = empty($element->label) ? '&nbsp;' : $element->label;

				$options = array();






Im currently working on version 3 (adding ‘sortable’ feature).

Please let me know more about your issues.

I think it’s best to do this by defining the form members:




$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,),

      ),

   

      // Invisible

      'id'=>array(

         'type'=>'hidden',

         'visible'=>false,  // not seen in the table

      ),

      'active'=>array(

         'type'=>'hidden',

         'visible'=>false,  // not seen in the table

      ),

));



In this way the labels ‘id’ and ‘active’ not shown in the table and the fields are sent with the form.

Is that correct? This worked for me. <_<

Regards.

Yes this is ok.

In the last release I didn’t pay attention to the ‘visible’ attribute.

I thought this is false for hidden elements but is always true for all FormInputElements.

I will change this behavior in the upcoming release, so you don’t need to add the invisible elements to the formConfig.

Thank you Joblo, for issue 2, I add the code as you suggest, it works! I am so happy.

for the issue 1, insert identity, I solved by add following code in the save function, I am a newbie learning Yii, I feel it may be not a good way , can you help me on how to do it better?




public static function save($model,&$validatedItems, &$deleteItems=array(), $masterValues = array() ,$formData = null)

	{

		//validate if empty: means no validation has been done

		$doValidate = empty($validatedItems) && empty($deleteItems);


		if ($doValidate)

		{

			//validate and assign $masterValues

			if (!self::validate($model, $validatedItems, $deleteItems, $masterValues , $formData))

				return false;

		}


		if (!empty($validatedItems))

			foreach ($validatedItems as $item)

			{

				if (!$doValidate)  //assign $masterValues

				{

					if (!empty($masterValues))

						$item->setAttributes($masterValues,false);

				}

                      if( empty($item['id']) ) unset($item['id']);   //<-this is added by me,how can I do it better?

				if (!$item->save())

					return false;

			}

           //$deleteItems = array of primary keys to delete

		if (!empty($deleteItems))...        



Maybe there’s a way to know $item[‘pkcolumnname’] instead of my hard coding?

Thank you again for helping. :)

Is there any way to append html next to a row element? I’m would like to add a hyperlink next to a drop down.

In the jqrelcopy documentation there is:

//Additional HTML to attach at the end of each copy.

‘append’=>CHtml::tag(‘span’,array(‘class’=>‘hint’),‘You can remove this line’),

But I tried adding this in my FormConfig array and it didn’t work.

There’s always jQuery’s after(), and I suppose I can create a widget for a dropdown hyperlink combination, but I would be surprised if there append is not built into multimodelform. Thanks.

If you want to pass a property value to jqrelcopy, you have to use ‘options’ of the widget.




  $this->widget('ext.jqrelcopy.JQRelcopy',array( //or multimodelform 

 ...

  'options'=>array('append'=>CHtml::tag('span',array('class'=>'hint')),

   ...



If you want to add additional html to the form you can add strings as elements in the formConfig





$memberFormConfig = array(

      'elements'=>array(

        'firstname'=>array(

            'type'=>'text',

            'maxlength'=>40,

        ),


       '<hr/>', //<--add html-code as string to the elements array


       CHtml::tag('span',array('class'=>'hint')), //<-- string

        ...

        

    ));




Will the first code append to all elements?

Will the 2nd set of code add another <div class="row">

how can I set detail form value?




if(isset($_POST['Master'],$_POST['Detail']))

    {

        $model->attributes=$_POST['Master'];

        $model->price=....(ok its  work)

 if( //validate detail before saving the master

            MultiModelForm::validate($detail,$validatedDetail,$deleteItems) &&

            $model->save()

           )

           {

            

            

            

             //the value for the foreign key 'groupid'

             $masterValues = array ('ID'=>$model->ID);

 

                $detail->attributes=$_POST['Detail'];

                $detail->color='Green';


.....

}



it doesnt work!

urgent: quick response without testing - please try yourself

  • ‘append’ will add code after cloning a fieldset/group

  • the 2nd set of code add another <div class="row"> because every form element is wrapped into the div

aatlikan: please take a look at the source code and see what happens on validate / save

The ‘$detail’ model will never been saved, its only for analysing the model structure/attributes.

In this extension you don’t have a single detail model, because of clientside cloning.

So you have an array of detailmodels ‘$validatedItems’ (the second parameter).

After calling validate, this array is populated with the submitted data of all detail models.

You can loop through this array and change the detail-models after calling MultiModelForm::validate and before calling MultiModelForm::save.

I tried the 2nd set of code but could not get it to appear. I did not try the 1st because I do not have a call to the JQRelcopy widget in my code. I was able to append a link next to a select box using jQuery’s after().

One issue with this is it appears Add Item will just copy the code from the first form element. I have code to add an update link when a record is selected in a drop down, and this gets copied over even when the select box is set to the empty record/Please Select value.

Do you know of an easier approach? I’m just looking for code to do:

<select> <a>Add</a> (if selected) <a>update</a>

Thanks.

I got it fixed using jsAfterClone to hide the update link

Hello again:

When I submit the form without validation errors it acts as normal. However if there are validation errors on the page I get the yii error page with this error. I checked $formData[$modelClass] and its empty after validation. Is this because the name of the form changes with validation errors? After validation error it adds [n__] to the name before the [0]. Here is the error:

    Invalid argument supplied for foreach()





    (REMOVED)/protected/extensions/multimodelform/MultiModelForm.php(439)





    427             foreach (&#036;allExistingPk as &#036;idx =&gt; &#036;delPks)


    428                 &#036;deleteItems[] = &#036;delPks;


    429 


    430         // remove handled formdata pk__


    431         unset(&#036;formData[&#036;modelClass]['pk__']);


    432 


    433         //----------- ADDED by jQuery -----------


    434 


    435         // use the first item as reference


    436         print_r(&#036;formData[&#036;modelClass]);  //I added this line to check the variable which is empty array


    437         &#036;refAttribute = key(&#036;formData[&#036;modelClass]);


    438         &#036;refArray = array_shift(&#036;formData[&#036;modelClass]);


    439         foreach(&#036;refArray as &#036;idx =&gt; &#036;value)


    440         {


    441             // check continue if all values are empty


    442             if (empty(&#036;value))


    443             {


    444                 &#036;allEmpty = true;


    445                 foreach (&#036;formData[&#036;modelClass] as &#036;attrKey =&gt; &#036;values)


    446                 {


    447                     if (is_array(&#036;values[&#036;idx])) //bugfix v2.1.1 have to check empty array items too


    448                     {


    449                         &#036;isEmpty = true;


    450                         foreach (&#036;formData[&#036;modelClass][&#036;attrKey] as &#036;item)


    451                         {





    Stack Trace


    #0     


    –


     /home/cam3/public_html/root/links/protected/extensions/multimodelform/MultiModelForm.php(329): MultiModelForm-&gt;initItems(array(TransactionsDetails), array(), array(), null)





    324         &#036;widget = new MultiModelForm;


    325         &#036;widget-&gt;model = &#036;model;


    326 


    327         &#036;widget-&gt;checkModel();


    328 


    329         if (&#33;&#036;widget-&gt;initItems(&#036;validatedItems, &#036;deleteItems, &#036;masterValues, &#036;formData))


    330             return false; //at least one item is not valid


    331         else


    332             return true;


    333     }


    334

Yes in ‘error’ mode, the cloned elements by jquery from the previous screen are rendered as [n__].

But there should always a ‘copyTemplate’ with the empty inputs be added as last item (see procedure run()).

The empty item should be added independent of the update- or errormode.

Therefore the $formData[$modelClass] should never be empty.

Hello:

What was going on was I followed this post to remove the extra record with an error:

http://www.yiiframework.com/forum/index.php?/topic/20289-extension-multimodelformjqrelcopy/page__p__102252#entry102252

What I did to fix the error when only error box are submitted is to copy the n__ values to the post array at the beginning of initItems like it was a normal submit. I had some issues with extra forms being shown until I added the unset n_


//allow error forms to submit data

        $formDataSet=false;

            foreach(array_keys($_POST[$modelClass]) as $modClassArrKey){

                if($modClassArrKey!= 'n__' && $modClassArrKey!='pk__' && $modClassArrKey!='u__'){

                    $formDataSet=true;

                }

            }

            if(!$formDataSet){

                foreach(array_keys($_POST[$modelClass]['n__']) as $nRows){

                    foreach(array_keys($_POST[$modelClass]['n__'][$nRows]) as $nFields){

                        $_POST[$modelClass][$nFields][$nRows]=$_POST[$modelClass]['n__'][$nRows][$nFields];

                    }

                }

                unset($_POST[$modelClass]['n__']);

            }