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've moved the forum!

Please use forum.silverstripe.org for any new questions (announcement).
The forum archive will stick around, but will be read only.

You can also use our Slack channel or StackOverflow to ask for help.
Check out our community overview for more options to contribute.

Data Model Questions /

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

SilverStripe 3: GridField with many_many_extraFields


Go to End


8 Posts   9047 Views

Avatar
willmorgan

Community Member, 11 Posts

15 October 2012 at 2:33am

Hey guys,

I've had a look around the codebase to figure out how to get extraFields working but I have to say I'm stumped.

My current getCMSFields GridField setup is:

$gfConfig = GridFieldConfig_RelationEditor::create();
$amenityList = $this->Amenities();
$amField = new GridField('Amenities', null, $amenityList, $gfConfig);

The Amenity getCMSFields is:

function getCMSFields() {
	return new FieldList(
		new TextField('Title', 'Name of amenity', null, 40),
		new TextField('TravelTime', 'Travel time to get there', null, 40)
	);
}

For TravelTime, I've tried various constructs like ParentPage.TravelTime etc, but no luck.

Has anyone done this before?

Avatar
BenWu

Community Member, 97 Posts

20 October 2012 at 9:40pm

I am looking for the same thing. According to this http://www.silverstripe.org/general-questions/show/7395 it looks like there is no built-in function for you to edit the many_many_extraFields data.

I think there are 2 ways to get around this:
1. Break the many_many relation down to 2 has_many relations:
check the example here http://www.balbuss.com/multiple-many-many-s-of-the-same-class/

2. Write your own formfield
In my project, as it is too late to use Method 1, I have to write my own formfield so that it can be added back into the admin. I am using the SubmittedFormField in the UserForm module as an example to write my scripts.

It's a shame it is hard for us to do this when SS3 should have taken care of this.
I have seen the Datagrid proposal here http://open.silverstripe.org/wiki/development/DataGrid which is exactly what I want when I have large amount of data to manage. However, it looks like this proposal is ignored.

If you have any quick way to do this, please share.

Avatar
martimiz

Forum Moderator, 1391 Posts

24 October 2012 at 12:45am

I too stumbled upon this issue again, and I really feel that this option should either be implemented in a simple to use way (preferred :) ) or be removed entirely. I was thinking of posting this at the core dev group, to see what others think. Looks Like someone really should now...

Martine

Avatar
willmorgan

Community Member, 11 Posts

24 January 2013 at 11:38am

Edited: 24/01/2013 11:38am

Hey guys,

I've found the way to do this. It's undocumented so far, as far as I can see anyway. Turns out it wasn't impossible after all - the API has changed though.

I did some digging in framework and found this inside GridFieldDataForm.php line 450:

$extraData = (isset($data['ManyMany'])) ? $data['ManyMany'] : null;

The highlighted line basically looks for ManyMany as an associative-array style entry in the CMS fields.

So the way around it is luckily quite simple!

Inside your many_many object's getCMSFields that you wish to add extra data to, you can add the field like so:

new TextField('ManyMany[ExtraFieldName]', 'Extra field')

Where "ExtraFieldName" is the name of the extraField you defined inside the $many_many_extraFields static.

Avatar
apiening

Community Member, 60 Posts

29 January 2013 at 6:34am

Hey guys,

I came accross the same issue yesterday. My problem is that I have a complex model where displaying the extra fields in getCMSFields is tricky. The context in which getCMSFields gets called varies, some extra fields may not be valid in some contexts. So I thought that the best place to display the extra form fields for my application is right in the gridfields list view. I made a very lightweight module and published it on github. In case anybody likes the idea of inline editing the extra fields in the gridfield, here it is:

https://github.com/smindel/silverstripe-gridfieldeditablemanymanyextracolumns

(hope you like the name)

Cheers

Andy

Avatar
lx

Community Member, 83 Posts

13 February 2013 at 10:22am

avengex, do you know if its possible to change the form that shows up when clicking on the edit button in the grid, to only show all formfields for the many_many_extrafields.

I have about 7-8 many_many_extrafields. And clicking on edit should only allow me to edit these.

I dont want to make changes to all properties of the User class.
To manage users i already have a modeladmin.

The problem is, that my modeladmin uses getCMSFields() to generate the Form. And the edit button in the grid also uses getCMSFields(). Is there a way to detect if i am in the modeladmin section or if i clicked on edit in the many_many grid.

thanks
lx

Avatar
willmorgan

Community Member, 11 Posts

13 February 2013 at 11:28am

Yes, this is slightly off topic, but it's possible. In 2.4 you could pass in the $detailFormFields of the DataObjectManager, and in 3.1 you now call setFields on a GridFieldDetailForm, passing in a FieldList object.

Avatar
torleif2

Community Member, 6 Posts

9 July 2015 at 2:23pm

Thanks Will and lx. Putting two and two together, you can use many_many arrays, GridFieldDetailFor, and GridFieldDataColumns to create an editable many many relationship that stores editable data on the relationship, instead of the target DataObject. Below is a trivial example that stores a list of members with their favorite fruit.


class ManyManyExamplePage extends Page {

	public static $many_many = array(
		'ManyManyExamplePage' => 'Member'
	);
	public static $many_many_extraFields = array(
		'ManyManyExamplePage' => array(
			'FavoriteFruit' => 'varchar(200)'
		)
	);

	public function getCMSFields() {
		$fields = parent::getCMSFields();

		$config = GridFieldConfig_RelationEditor::create();

		$config->removeComponentsByType(new GridFieldDetailForm());
		$config->removeComponentsByType(new GridFieldDataColumns());
		$config->removeComponentsByType(new GridFieldAddNewButton());
		
		$edittest = new GridFieldDetailForm();
		$edittest->setFields(FieldList::create(
			TextField::create('ManyMany[FavoriteFruit]', 'FavoriteFruit')
		));
		$summaryfieldsconf = new GridFieldDataColumns();
		$summaryfieldsconf->setDisplayFields(array( 'FavoriteFruit' => 'Favorite Fruit', 'Name' => 'Member'));
		
		$config->addComponent($edittest);
		$config->addComponent($summaryfieldsconf, new GridFieldFilterHeader());

		$field = GridField::create('ManyManyExamplePage', null, $this->ManyManyExamplePage(), $config);
		$fields->addFieldToTab('Root.Main', $field);

		return $fields;
	}

}
class ManyManyExamplePage_Controller extends Page_Controller {
	
}