The Relation widget is used in forms, where the User can choose between a selection of related elements.
It automatically renders a Selectbox or Listbox. Every Type of Relation is supported (even MANY_MANY since 0.8).
The Relation widget is used in forms, where the User can choose between a selection of model elements, that this models belongs to.
Since version 0.8 it is able to handle BELONGS_TO, HAS_ONE and MANY_MANY Relations. The Relation type is detected automatically from the Model 'relations()' section.
The following example shows how to use Relation with a minimal config, assuming we have a Model "Post" and "User", where one User belongs to a Post:
$this->widget('application.components.Relation', array( 'model' => 'Post', 'relation' => 'user' 'fields' => 'username' // show the field "username" of the parent element ));
Results in a selectbox in which the user can choose between all available Users in the Database. The shown field of the Table "User" is "username" in this example.
You can choose the Style of your Widget in the 'style' option. Note that a Many_Many Relation always gets rendered as a Listbox, since you can select multiple Elements.
'fields' can be an array or an string. If you pass an array to 'fields', the Widget will display every field in this array. If you want to show further sub-relations, separate the values with '.', for example: 'fields' => 'array('parent.grandparent.description')
Optional Parameters:
You can use 'field' => 'post_userid' if the field in the model that represents the foreign model is called different than in the relation
Use 'foreignField' => 'id_of_user' if the primary Key of the Foreign Model differs from the one given in the relation.
Normally you shouldn´t use this fields cause the Widget get the relations automatically from the relation.
Use 'allowEmpty' to let the user be able to choose no parent. The string assigned to 'emptyString' will be displayed.
With 'hideAddButton' => 'true' you can hide the 'create new Foreignkey' Button generated beside the Selectbox.
Define the AddButtonString with 'addButtonString' => 'Add...'. This string is set default to '+'
When using the '+' button you most likely want to return to where you came. To accomplish this, we pass a 'returnTo' parameter by $_GET. The Controller can send the user back to where he came from this way:
if($model->save()) if(isset($_GET['returnTo'])) $this->redirect(array(urldecode($_GET['returnTo'])));
Using the 'style' option we can configure if we want our widget to be rendered as a 'Selectbox' (default) or a 'ListBox'.
Use the option 'createAction' if the action to add additional foreign Model options differs from 'create'.
With 'parentObjects' you can limit the Parent Elements that are being shown. It takes an array of elements that could be returned from an scope or an SQL Query.
The parentObjects can be grouped, for example, with 'groupParentBy' => 'city'
Use the option 'htmlOptions' to pass any html Options to the Selectbox/Listbox form element.
hint: ManyMany Records can easily be saved by using the CAdvancedArBehavior Behavior.
Full Example:
$this->widget('application.components.Relation', array( 'model' => 'Post', 'field' => 'Userid', 'style' => 'ListBox', 'parentObjects' => Parentmodel::model()->findAll('userid = 17'), 'groupParentsBy' => 'city', 'relation' => 'user', 'foreignField' => 'id_of_user', 'fields' => array( 'username', 'username.group.groupid' ), 'delimiter' => ' -> ', // default: ' | ' 'returnTo' => 'model/create', 'createAction' => 'add', // default: 'create' 'addButtonString' => 'click here to add a new User', // default: '' 'htmlOptions' => array('style' => 'width: 100px;') ));
Total 8 comments
It's now called relatedPk but the author did not update the page, only the code.
Thanks for this extension but it may help someone
School Model
'owners' => array(self::MANY_MANY, 'User', 'tbl_users_schools(school_id,user_id)')
So listbox will not set already assigned object as selected until I add space between fields in many to many table definition
So it works right this way
'owners' => array(self::MANY_MANY, 'User', 'tbl_users_schools(school_id, user_id)')
Hi! You have a little bug at line 303 It takes “id” as model's PK
and this code fails if schema has different PK name. I made a little fix:
Now it works.
it is interesting that people still find and use the relation widget.
there is a much-newer version available here:
http://code.google.com/p/gii-template-collection/source/browse/trunk/gtc/components/Relation.php
maybe i find the time and package this some time
Hi,
thank for the great widget
I have encountered a problem with a relation to a Model which table has a PK which is not 'id'.
I have changed line 405 :
to
$objects[$relobj->{$relobj->getMetadata()->tableSchema->primaryKey}] = $relobj;
It seems to do the trick, would the author comment on this ?
Thanks
would be nice to see the documentation of this updated - i only found the bug mentioned by #1383 after some own research (: but the code is very clear and so that was ok
another bug: the "add new" button assumes the controller sounds the same as the relation-table.. would be nice to have this configurable
@#1545 if you want your selected data displayed then set 'model'=>$model this feature isn't documented (:
and here my code which i use to save my many_many relation.. perhaps this can be done easier <code<?php //before save(): if(isset($_POST['Entrytype'])) { $model->attributes=$_POST['Entrytype']; $model->categories = $this->getListOfManyMany('Category'); $model->save() }
public function getListOfManyMany($otherClass) { $thisClass = 'Entrytype'; $i = 0; $arr = array(); while(true) { $i++; $str = 'rel-'.$i.'-'.$thisClass; if (isset($_POST[$str][$otherClass])) { $val = $_POST[$str][$otherClass]; if (!empty($val)) $arr[] = $val; } else break; } return $arr; }sorry for the bad code intendention :s and perhaps someone has a better idea to do this - would be nice to see one here
This in conjunction with the CAdvancedarbehavior extension definitely saves some time.
Would like to see both of them extended further and added to the trunk.
My only issue currently is that I can't get it to use the saved data to display what has been previously selected on update.
helps to simplify using many-many on display. great features such as returnTo. Overall like where this extension is headed. It will be a time saver as it improves.
minor issues:
in documentation returnTo option is actually returnLink and creates a returnTo parameter for _GET
in documentation addButtonString does not exist: showAddButton contains the text to display or false to not display
data is not showing as selected in my listbox.
Leave a comment
Please login to leave your comment.