Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

We're retiring the forums!

The SilverStripe forums have passed their heyday. They'll stick around, but will be read only. We'd encourage you to get involved in the community via the following channels instead:

Data Model Questions /

Moderators: martimiz, Sean, Ed, biapar, Willr, Ingo, swaiba

ComplexTableField inside a ComplexTableField

Go to End



Community Member, 4 Posts

29 December 2010 at 11:43pm

Edited: 29/12/2010 11:43pm

I need to have the following scenario:

Members have_many Pets
Pets have a number of Treatments, which are common to all pets (ie. many_many relation)

I have a ModelAdmin subclass (MyMemberAdmin) with $managed_models = array('Member', 'Treatment'). The Member class has a DataObjectDecorator that adds a ComplexTableField for managing Pets. Finally, the Pet model has a ManyManyComplexTableField that allows adding and removing Treatments.

This all works fine, until the Pet form is submitted, and the selected Treatments are not stored. I think it's because the ManyManyComplexTableField isn't putting the correct hidden fields into the form because it thinks that the parentClass is "Member", not "Pet"

If I change things around so that the ManyManyComplexTableField is not accessed through a popup then the problem doesn't occur.

I've attached the code I'm using to this post. All you need to do to get this running is add "Object::add_extension('Member', 'MyMember');" to mysite/_config.php and run a dev/build. You can then go to "admin/members" and create a Treatment, then edit a Member, add a Pet and select the Treatment. When you click submit you'll see that the Treatments don't get stored.

I would really appreciate some help with this. Also I think that this would be a very cool feature if it were possible to do this :)


Object::add_extension('Member', 'MyMember');


class MyMember extends DataObjectDecorator {
	function extraStatics() {
		return array(
			'has_many' => array(
				'Pets' => 'Pet'
	public function updateCMSFields(FieldSet $fields) {
		$owner = $this->getOwner();
		$pets = new ComplexTableField(
			$controller = $owner,
			$name = 'Pets',
			$sourceClass = 'Pet',
			$fieldList = array('Name' => 'Name', 'DateOfBirth' => 'DOB'),
			$detailFormFields = 'getCMSFields',
			$sourceFilter = "`OwnerID` = '{$owner->ID}'"
		$fields->addFieldToTab("Root.Pets", $pets);



class MyMemberAdmin extends ModelAdmin {

	public static $managed_models = array(

	static $url_segment = 'members';
	static $menu_title = 'Members';

	function __construct() {
		$this->showImportForm = false;



class Pet extends DataObject {

	public static $db = array(
		'Name' => 'Text',
		'DateOfBirth' => 'Date'

	public static $has_one = array(
		 'Owner' => 'Member'

	public static $many_many = array(
		'Treatments' => 'Treatment'

	function getCMSFields() {
		$fields = parent::getCMSFields(array('include_relations' => false));
		$dateOfBirth = new DateField('DateOfBirth', 'Birth Date');
		$dateOfBirth->setConfig('showcalendar', true);
		$fields->addFieldsToTab('Root.Main', array(
			new TextField('Name'),
		$treatments = new ManyManyComplexTableField(
			$controller = $this,
			$name = 'Treatments',
			$sourceClass = 'Treatment',
			$fieldList = array('Name' => 'Name')
		$fields->addFieldsToTab('Root.Treatments', array(
		return $fields;



class Treatment extends DataObject {

	public static $db = array(
		'Name' => 'Text'

	public static $many_many = array(
		 'Pets' => 'Pet'

	function getCMSFields() {
		$fields = new FieldSet(
			new TextField('Name')
		return $fields;


Attached Files