[Feature request] improving CMS field ordering

150 views
Skip to first unread message

g4b0

unread,
Jan 16, 2013, 10:57:09 AM1/16/13
to silverst...@googlegroups.com
Hi all,
I think that "insertBefore" parameter of FieldList::addFieldToTab is not sufficient. I'm working on a large site with a deep inheritance and a lot of DataExtension::updateCmsField(), and I can't place CMS Field where I want, also because during extension the CMS itself doesn't know the entire field list.

My proposal is simple, and come from Drupal. We can add a numerical "weight" to the field, so that the heavier (high number) field will be placed at the bottom, while the lightest (low number) will be placed at the top. Maybe it's possible to mantain the actual system, adding a default 0 weight to all fields. If weight is specified has the precedence, otherwise the system can fallback to the actual system.

What do you think about that? I can try to code it and submit a pull request, but I'm not sure my SS knowledge is sufficient...

g4b0

Josua

unread,
Jan 16, 2013, 11:23:45 AM1/16/13
to silverst...@googlegroups.com

IMHO, it may be an interesting system to better organize the fields.

Regards,
Jose A.

g4b0

unread,
Jan 22, 2013, 5:42:35 AM1/22/13
to silverst...@googlegroups.com

Il giorno mercoledì 16 gennaio 2013 16:57:09 UTC+1, g4b0 ha scritto:
I can try to code it and submit a pull request, but I'm not sure my SS knowledge is sufficient...

Any hint about what files I have to manipulate? 

Thanks
g4b0

Ingo Schommer

unread,
Jan 22, 2013, 8:22:02 AM1/22/13
to silverst...@googlegroups.com
I think this is overcomplicating the FieldSet API for an advanced use case.
It would go against any usage of $before/$after parameters and the insertBefore()/insertAfter(),
or make them very hard to understand in case it tries to auto-assign its own numerical priorities based on them.

If the extension relies on knowing the entire field list, a workaround is to make
the updateCMSFields() method fault tolerant enough to be applied multiple times,
and then call updateCMSFields() throughout the subclasses.
On the long run, I think we need a wrapper around getCMSFields()
which handles these invocation concerns, rather than leaving it in user space.
This wrapper could then be a bit smarter about prioritizing certain extensions,
e.g. call Translatable->updateCMSFields() *after* all other updateCMSFields().

g4b0

unread,
Jan 22, 2013, 9:00:26 AM1/22/13
to silverst...@googlegroups.com
Il giorno martedì 22 gennaio 2013 14:22:02 UTC+1, Ingo Schommer ha scritto:
I think this is overcomplicating the FieldSet API for an advanced use case.
It would go against any usage of $before/$after parameters and the insertBefore()/insertAfter(),
or make them very hard to understand in case it tries to auto-assign its own numerical priorities based on them.

The actual FieldList::addFieldToTab only permit to put a FormField *before* another, so in userspace it's impossible (or at lest counter-intuitive) to put a FormField at the end of the FieldList. In addition I think that the actual ordering method is really complicated, especially when arise lot of inheritance/extension.

A numerical weight is a really simple concept, during getCmsField() or updateCmsField() the developer have just to insert a $field->setWeight(100); if he want the field to be the last, or $field->setWeight(-100); if he want the field to be the first. Default weight can be 0, and in case of same weight the field can be ordered alphabetically, or just in the older way.
 
If the extension relies on knowing the entire field list,

The extension need to put some FormFields in the correct position, it does not necessarily relies on knowing the entire field list.
 
a workaround is to make
the updateCMSFields() method fault tolerant enough to be applied multiple times,
and then call updateCMSFields() throughout the subclasses.

I did it for some page, but it's difficult to do with DataObjects, since they don't implement disableCMSFieldsExtensions():

/************************
******** PAGE ********
*************************/
public function getCMSFields() {

// Ottengo l'elenco dei Fields
SiteTree::disableCMSFieldsExtensions();
$fields = parent::getCMSFields();
SiteTree::enableCMSFieldsExtensions();

/* Subtitle */
$field = new TextareaField('Subtitle');
$field->setTitle('Sottotitolo');
$fields->addFieldToTab('Root.Main', $field, 'Content');

// Chiamo l'updateCMSFields che ho soppresso all'inizio della funzione
$this->extend('updateCMSFields', $fields);

return $fields;
}
 
/************************
**** EXTENSION *****
*************************/
public function updateCMSFields(\FieldList $fields) {

parent::updateCMSFields($fields);

/* SliderImage */
$field = new UploadField('SliderImage');
$field->setTitle('Immagine Slider');
$fields->addFieldToTab('Root.Main', $field, 'Content');

/* PositionInScroller */
$field = new DropdownField('PositionInScroller', 'Posizione nello Scroller', self::$positions);
$field->setTitle('Posizione nello Scroller');
$fields->addFieldToTab('Root.Main', $field, 'SliderImage');
}


It works, but I think that this technique is inefficient and again counter-intuitive as well as impossible to run on DataObjects. 

Furthermore I can develop my updateCMSFields() method fault tolerant enough to be applied multiple times, but I don't know how many extension I will apply to my DataObjects, maybe in the future I will want to use a module developed from GitHub and the behavior will be unpredictable. 

On the long run, I think we need a wrapper around getCMSFields()
which handles these invocation concerns, rather than leaving it in user space.
This wrapper could then be a bit smarter about prioritizing certain extensions,
e.g. call Translatable->updateCMSFields() *after* all other updateCMSFields().

In a perfect world the FieldList have to be accessible during the updateCMSFields() and not *after* it, so ordering will be possible. But it will still be difficult to put a field at the end of the list :)

My 2 cent
g4b0

g4b0

unread,
Jan 23, 2013, 9:12:06 AM1/23/13
to silverst...@googlegroups.com
I did it :) 


Il giorno martedì 22 gennaio 2013 14:22:02 UTC+1, Ingo Schommer ha scritto:
I think this is overcomplicating the FieldSet API for an advanced use case.

~30 line of code, excluding comments. It works at the end of the EditForm creation, after the actual sorting algorithm, in a really transparent way. In userland the developer can add a weight to a field to let it going up or down, depending of the other fields weight. Default weight is 0. If $field->setWeight($weight); is not called normal sorting still works:

/* Test */
$field = new TextField('Test');
$field->setTitle('Test');
$field->setWeight(100); // Test field will be the last
$fields->addFieldToTab('Root.Main', $field, 'Content');
 
It would go against any usage of $before/$after parameters and the insertBefore()/insertAfter(),
or make them very hard to understand in case it tries to auto-assign its own numerical priorities based on them.

Not correct. It works alongside insertBefore()/insertAfter(), to be precise it works *after* the normal sorting, adding a negligible overhead.

You can have a look to the code here:

Can I submit a pull request? 

g4b0
Reply all
Reply to author
Forward
0 new messages