[EXTENSION] multimodelform/jqrelcopy

Maybe the bugfix.

Change the line 942 (v. 3.0) in the method ‘renderTableHeader()’-




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

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

            {



when I try to add html-code as a string to the array i get the following error messg:

CFormStringElement and its behaviors do not have a method or closure named "getRequired".

Here’s the code.




$perfreviewsubFormConfig = array(

      'elements'=>array(

        'standardname'=>array(

            'id'=>'standardid',

            'label'=>'Standard',

            'type'=>'textarea',

            'rows'=>'6',

            'cols'=>'30',

            'disabled'=>'disabled',

             'resize'=>'none'

        ),


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


        'elementname'=>array(

            'label'=>'Element',

            'type'=>'textarea',

            'rows'=>'5',

            'cols'=>'30',

            'disabled'=>'disabled',

        ),

        'ratingid'=>array(

            'type'=>'radiolist',

            'items'=>PerfReview::model()->getRatingOptions(),

            //'prompt'=>'Please Select Rating:',

        ),

      

    ));



What did I do wrong?

Strange … take a look at the code in line 998

Seems you have to debug through the method renderFormElements().

An element should only be rendered if it has a ‘name’ means it is an attribute of the model.

The ‘<hr>’ element is type of CFormStringElement and will not be rendered to the output and ‘required’ will not be checked.




 protected function renderFormElements()

    {

        $output = '';


        $elements = $this->getElements();


        foreach ($elements as $element)

        {

            if (isset($element->name)) //element is an attribute of the model

            {

                $elemName = $element->name;

                ...

             }

        }

         else  //CFormStringElement...  Bugfix in the next release

                $output .= $element->render();






But there is a bug, because <hr/> will not be rendered, so I have to add the ‘else’ part.

Hi,

you just have to replace content of variables $addItemText and $removeText to ‘’, and the links won’t appear no more.

Perhaps there’s a best way to do it, but that works for me.

(this answer is about the question of Th3 R00ST3R posted yesterday at 11:18)

Thank you Joblo, it works perfect!

Have a nice day

Hi,

Sorry but I changed the values of the variables to ‘’ and it still shows the ADD and Remove text. do I need to clear the cache?

EDIT - Nevermind, I got it to work. I am an idiot and was putting the single quotes inside the other single quotes. duh!

**EDIT 2 ** - Now I just need to get rid of the blank row at the bottome of the form. Any way to disable that?

Edit 2: You have to change the source this. Search for $showAddLink and set it to false.

But I don’t understand.

Why do you use the multimodelform extension, when you hide all the features the extension was built for?

I this case a CListView would be the choice for you.

I have released v3.1 with the bugfixes discussed above

and the new properties ‘allowAddItem’ and ‘allowRemoveItem’ to disable adding or removing items.

I made the above post almost a year ago, and it is now fixed unfortunately, I think this preceeded to break checkboxes.

2628

Screen shot 2012-03-05 at 9.34.21 AM.png

In the attached image, you can see that yii has a hidden element and the checkbox both named Items[otherOpt][]

What this causes, is that the checkboxes get knocked off so if you check the first box, item 2 actually gets checked since the hidden field is 0 and the checkbox is 1.

2629

Screen shot 2012-03-05 at 9.43.41 AM.png

In update view, this is not a problem because the id is set so they don’t extend each other, but if you create more items with JS they don’t have the index set so it is a problem.

I think the only way to fix this would be to have JS include ids in the array.

Also, for some reason, the new items added by JS are now checked. I’m not sure what has caused this.

I’m happy to help with trying to code fixes, but I’m not exactly sure where to start. I feel like building in the array indexes will require quite a few code changes. Maybe it is just that the hidden fields for checkboxes need to be processed differently by the addon?

Hi,

Thanks for adding the true/false to the ADD and Remove items, that helps alot since I am pre-populating the form and not allowing for additional records.

The issue I am seeing now is that I have one main record(1st model), and 28 sub records(2nd model) on the one form. It’s not saving the sub records above the 23rd record. I can edit the first 23 records, no problem, but any values I change on the 24th or above record doesn’t save the change. i don’t know if that number is consistent or not.

The question is, is there a limit to the number of records that you can edit on the 2nd model sub form?

edit

Also, is there a way to have paging on the 2nd model?

Thank you very much!

Th3 R00ST3R:

No there is no limit of detail records in the code.

Is there a js-error message in the firebug-console?

Loren:

Can you submit a sample code where I can investigate your issues?

You can (for example) extend the multimodelform 3.0 demo code.

EDIT

After I turned on the warnings, firebug output the following:

Use of getAttributeNode() is deprecated. Use getAttribute() instead.

Use of getAttributeNodeNS() is deprecated. Use getAttributeNS() instead.

No, the console window is empty. It’s strange, the first 20 or so records I will save the update, the ones past that will not.

Here’s some sample code from the controller:


 public function actionUpdate($id)

  	{

  	  Yii::import('ext.multimodelform.MultiModelForm');

  	  

  		$model=$this->loadModel($id); //The Performance Review model

  		

  		$perfreviewsub = new PerfReviewSub;

  		$validatedPerfreviewsub = array(); //ensure an empty array

  

  		// Uncomment the following line if AJAX validation is needed

  		 $this->performAjaxValidation($model,$perfreviewsub);

  

  		if(isset($_POST['PerfReview']))

  		{

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

  			//the value for the foreign key 'performancereviewid'

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

        

        if(//Save the parent model after saving child sub records

          MultiModelForm::save($perfreviewsub,$validatedPerfreviewsub,$deletePerfreviewsub,$masterValues) &&

          

          $model->save()

          )

  				$this->redirect(array('update','id'=>$model->performancereviewid));

  		}

  

  		$this->render('update',array(

  			'model'=>$model,

  			//submit the sub and validatedItems to the widget in the edit form

        'perfreviewsub'=>$perfreviewsub,

        '$validatedPerfreviewsub' => $validatedPerfreviewsub,

  		));

  	}

And here’s the code from the _form


$perfreviewsubFormConfig = array(

      'elements'=>array(

        'standardname'=>array(

            'id'=>'standardid',

            'label'=>'Standard',

            'type'=>'textarea',

            'rows'=>'4',

            'cols'=>'65',

            'disabled'=>'disabled',

            'resize'=>'none'

        ), 

        'elementname'=>array(

            'label'=>'Element',

            'type'=>'textarea',

            'rows'=>'4',

            'cols'=>'65',

            'disabled'=>'disabled',

        ),

        'ratingid'=>array(

            'type'=>'radiolist',

            'items'=>PerfReview_Admin::model()->getRatingOptions(),

            //'prompt'=>'Please Select Rating:',

        ),

               

    ));

 

$this->widget('ext.multimodelform.MultiModelForm',array(

        'id' => 'id_perfreviewsub2', //the unique widget id

        'tableView' => true,

        'formConfig' => $perfreviewsubFormConfig, //the form configuration array

        'model' => $perfreviewsub, //instance of the form model

        

        

        //if submitted not empty from the controller,

        //the form will be rendered with validation errors

        'validatedItems' => $validatedPerfReviewSub,

 

        //array of perfreviewsub instances loaded from db

        'data' => $perfreviewsub->findAll('(performancereviewid=:performancereviewid) order by standardid, elementid', array(':performancereviewid'=>$model->performancereviewid)),

    ));  

There are only 3 columns on the 2nd model (sub records), and only the ratingid gets updated. The first two columns are pre-populated and are disabled.

Maybe it’s a sideeffect of ‘$this->performAjaxValidation($model,$perfreviewsub);’ ?

I didn’t test multimodelforms with ajax validation.

Does it work if you comment this line?

Thanks for the reply. No, commenting the AjaxValidation does not change correct the issue.

Here is the code from the form file which should be enough to emulate it since all you should need to do is add a checkbox field to the form and it should start messing up.




    	<?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

 

$itemFormConfig = array(

	'elements'=>array(

    	'item'=>array(

        	'type'=>'text',

        	'maxlength'=>50,

    	),

    	'bringing'=>array(

        	'type'=>'text',

        	'maxlength'=>32,

    	),

    	'otherOpt'=>array(

        	'type'=>'checkbox',

    	),

    	'other'=>array(

        	'type'=>'text',

        	'maxlength'=>50,

    	),

    	'order'=>array(

        	'type'=>'text',

        	'maxlength'=>3,

        	'size'=>2

    	),

	)

);

 

$this->widget('ext.multimodelform.MultiModelForm',array(

    	'id' => 'id_items', //the unique widget id

    	'formConfig' => $itemFormConfig, //the form configuration array

    	'model' => $item, //instance of the form model

 

    	//if submitted not empty from the controller,

    	//the form will be rendered with validation errors

    	'validatedItems' => $validItems,

    	'tableView' => true,

    	//array of member instances loaded from db

    	'data' => $item->findAll(array(

        	'condition' => 'menu_id=:menuId',

        	'params' => array(':menuId'=>$model->id),

        	'order' => '`order` asc'

    	)),

	));

?>

If not, I have also zipped my whole application and attached it. (Don’t worry, passwords were removed first.)

Ok, I did a print_r() in the Save function of the MultiModelForm.php like so:


//if sortable, assign the sortAttribute

                if (!empty($sortAttribute))

                {

                    $sortIndex++;

                    $item->$sortAttribute = $sortIndex;

                }


                print_r($item);

                

                if (!$item->save())

                    return false;

There are 38 records total and the record id’s I have on the form of the 2nd model are 1677-1714.

I reviewed the output from print_r() and I see that it updates records 1677-1695 and 1695 is the last record output from the print_r() function. It does not print 1696-1714 as if it’s not looping through all the records when it saves.

I hope this makes sense and hope you can help. thanks!

Maybe an issue of limited POST data?

  • post-max-size?

  • suhosin

As you can see in the code I have no limit there.

As I told above, when you don’t use the cloning feature of the multimodelform a better solution for you will be a CDetailView …

Loren:

In your project I’m missing the database creation file in protected/data for the table menu and items

Not to sound condescending, but whether or not I use the cloning feature of the model is irrelevant to the issue at hand. I like the ease of your extension, but just don’t need that particular feature on this particular form as the data is pre-populated. I will check the POST data to see if there is a limitation. Thanks for the tip!

EDIT You nailed it. unbeknownst to me, Suhosin was installed in the server. I changed the suhosin.post.max_vars = 2048 and suhosin.request.max_vars = 2048 in the suhosin.ini file and it worked! Thanks again for the extension and the tip!

Sorry, working in too many frameworks. I’ve been working in Django which creates the database from the code. I forgot Yii creates code from the database.