undefinedoffset / sortablegridfield Goto Github PK
View Code? Open in Web Editor NEWAdds drag and drop functionality to Silverstripe's GridField
License: BSD 3-Clause "New" or "Revised" License
Adds drag and drop functionality to Silverstripe's GridField
License: BSD 3-Clause "New" or "Revised" License
On 3.1.x-dev, with phpunit 3.7.
1) GridFieldSortableRowsTest::testSortActionWithAdminPermission
No items to sort
/Users/ingo/Silverstripe/ss-3.1/sortablegridfield/code/forms/GridFieldSortableRows.php:223
/Users/ingo/Silverstripe/ss-3.1/sortablegridfield/code/forms/GridFieldSortableRows.php:206
/Users/ingo/Silverstripe/ss-3.1/framework/forms/gridfield/GridField.php:653
/Users/ingo/Silverstripe/ss-3.1/framework/forms/gridfield/GridField.php:615
/Users/ingo/Silverstripe/ss-3.1/sortablegridfield/tests/forms/GridFieldSortableRowsTest.php:43
/opt/local/lib/php53/share/pear/PHPUnit/TextUI/Command.php:176
/opt/local/lib/php53/share/pear/PHPUnit/TextUI/Command.php:129
/opt/local/bin/phpunit:46
Hi,
I'm not sure if this is where I submit requests but here goes,
I am working on a site where the client has requested to be able to sort DataObjects which are in visible in a ModelAdmin GridField, they have too many objects to sort by hand so I was woundering if you have thought of making a simple selectbox in the GridField actions to update the sort order alphabetically quickly and efficiently?
I have just installed the SortableGridFeild module.
I have tried to add sorting to my existing dataobject and page:
ImageResource.php
class ImageResource extends DataObject
{
public static $db = array (
'Title' => 'Text',
'Caption' => 'Text',
'SortID'=>'Int'
);
/* public static $default_sort='SortOrder'; */
static $has_one = array (
'Attachment' => 'Image', //Needs to be an image
'SuperSizePage' => 'SuperSizePage',
'HomePage' => 'HomePage'
);
public static $summary_fields = array(
'Thumbnail'=>'Thumbnail',
'Title' => 'Title'
);
public function getThumbnail() {
if ($Image = $this->Attachment()->ID) {
return $this->Attachment()->SetWidth(80);
} else {
return '(No Image)';
}
}
public function getCMSFields()
{
return new Fieldlist(
new TextField('Title'),
new TextareaField('Caption'),
new UploadField('Attachment')
);
}
}
and the homepage.php
'Image' ); ``` static $has_many = array ( 'Images' => 'ImageResource' ); ``` function getCMSFields() { $fields = parent::getCMSFields(); ``` /* ``` $manager = new ImageDataObjectManager( $this, // Controller 'Images', // Source name 'ImageResource', // Source class 'Attachment', // File name on DataObject array( 'Title' => 'Title', 'Caption' => 'Caption' ), // Headings 'getCMSFields_forPopup' // Detail fields // Filter clause // Sort clause // Join clause ); */ $fields->addFieldToTab('Root.Media', new UploadField('Photo', 'First Column Image')); ``` $fields->addFieldToTab("Root.Gallery", new HeaderField("Images for the gallery","2")); ``` /\* $fields->addFieldToTab("Root.Gallery",$manager); */ ``` $config = GridFieldConfig_RelationEditor::create(); ``` /\* $config->addComponent(new GridFieldSortableRows('SortOrder')); _/ // Set the names and data for our gridfield columns /_ $config->getComponentByType('GridFieldDataColumns')->setDisplayFields(array( 'Images' => 'Images', 'Title' => 'Title', 'Attachment' => 'Attachement' 'Project.Title'=> 'Project' // Retrieve from a has-one relationship )); */ // Create a gridfield to hold the student relationship $imagesField = new GridField( 'Images', // Field name 'ImageResource', // Field title $this->Images(), // List of all related students $config ); // Create a tab named "Students" and add our field to it $fields->addFieldToTab('Root.Gallery', $imagesField); ``` return $fields; } ``` } class HomePage_Controller extends Page_Controller { ``` function LatestNews($num=2) { $news = DataObject::get_one("BlogHolder"); return ($news) ? DataObject::get("BlogEntry", "ParentID = $news->ID", "Date DESC", "", $num) : false; } ``` /* function UpcomingEvents() { return DataObject::get_one("calendar")->UpcomingEvents(2); } */ public function init() { parent::init(); Requirements::javascript(MODULE_SUPERSIZE_DIR . '/js/jquery.easing.min.js'); Requirements::javascript(MODULE_SUPERSIZE_DIR . '/js/supersized.3.2.5.min.js'); Requirements::javascript(MODULE_SUPERSIZE_DIR . '/theme/supersized.shutter.min.js'); ``` } ``` }Hi, i would be cool when your Module supports his functionality for ModelAdmin generated GridFields.
I get it work after adding a few lines of code into the getEditForm Method by Overlading the ModelAdmin:
function getEditForm($id = null, $fields = null) {
$list = $this->getList();
$exportButton = new GridFieldExportButton('before');
$exportButton->setExportColumns($this->getExportFields());
$listField = GridField::create(
$this->sanitiseClassName($this->modelClass),
false,
$list,
$fieldConfig = GridFieldConfig_RecordEditor::create($this->stat('page_length'))
->addComponent($exportButton)
->removeComponentsByType('GridFieldFilterHeader')
->addComponents(new GridFieldPrintButton('before'))
);
....
$class = $this->modelClass;
if($class::$default_sort != null) {
$conf=GridFieldConfig_RelationEditor::create(10);
$conf->addComponent(new GridFieldSortableRows($class::$default_sort));
$listField->setConfig($conf);
}
.....
}
But i get this Notice when i dragged&dropped some Row:
[19-Aug-2012 00:04:30] Notice at SortableGridField/code/forms/GridFieldSortableRows.php line 214: Object of class GridState_Data could not be converted to int (http://fritz-mueller-gmbh.dev/admin/contactadmin/Devision/EditForm/field/Devision)
I fixed it by adding this:
if ($paginator = $gridField->getConfig()->getComponentsByType('GridFieldPaginator')->First()) {
$pageState = $gridField->State->GridFieldPaginator;
$currentPage = $pageState->currentPage;
if(is_int($currentPage)) {
if($pageState->currentPage && $pageState->currentPage>1) {
$pageOffset = $paginator->getItemsPerPage() \* ($pageState->currentPage - 1);
}
}
}
I think its better to extend the ModelAdmin instead of my overloading method.
How do you increase the 'SortOrder" Field when somebody add new Records?
Maybe you forget on the TestDataObject something like this? :
function onBeforeWrite()
{
if(empty($this->Sort)) {
$query = new SQLQuery();
$query->select(array("max(Sort) as Sort"));
$query->from("Devision");
$result = $query->execute();
$record = $result->first();
if($record) {
$this->Sort = $record['Sort'] + 1;
} else {
$this->Sort = 1;
}
}
parent::onBeforeWrite();
}
In your Example?
Maybe to decorate the obBeforeWrite Method of the DataObject like this
$sortField = self::$default_sort;
if(empty($this->$sortField)) {
$query = new SQLQuery();
$query->selectField("max($sortField)", $sortField);
$query->setFrom(get_class());
$result = $query->execute();
$record = $result->first();
if($record) {
$this->$sortField = $record[$sortField] + 1;
} else {
$this->$sortField = 1;
}
}
should be nice
I am guessing this is not an 'issue' as such as it seems to be intended behaviour but I cannot see any reason why.
I am using a GridField to display a number of 'ExportCheckpoint' DataObjects. These DataObject's have no relationships of any kind to anything else (i.e. are not related to a specific page or other type of DataObject). The have a 'SortOrder' field which is also used as its default sort (in ASC order).
Basically I am using GridFieldSortableRows to allow for these DataObjects to be re-ordered, because when you click the 'allow drag and drop re-ordering' checkbox it sorts by 'SortOrder ASC' I am having to make my 'active' ExportCheckpoint be the one with the LOWEST SortOrder value. The CMS users can then drag and drop an older ExportCheckpoint to the top of the GridField (giving it a lower SortOrder).
By default newly created DataObject's would go to the bottom of the list (with the highest SortOrder) so I have enabled the 'append to top' setting. I was expecting this to set the newly created DataObject's SortOrder to 1 and then +1 to all other existing DataObjects in the list.
That seems to be exactly what the code does when $append_to_top == true AND the GridField's list is a RelationList however, the below code prevents this if the GridField's list is not a RelationList (and is a regular DataList presumably):
GridFieldSortableRows.php ln 219 - 221
if($this->append_to_top && !($list instanceof RelationList)) {
$idCondition='"ID" IN(\''.implode("','", $list->getIDList()).'\')';
}
This code add an extra WHERE condition which will only apply the '+1 to all SortOrder fields' logic to the newly created DataObject and not to any of the existing ones.
That leaves the scenario where you have multiple items in the list all with the same SortOrder of 1 (as per the attached screenshot - I have added 'Sort Order' and 'Chronological Order' to the GridField columns to make this clear).
I can prevent this by replacing the above code with this:
if($this->append_to_top && !($list instanceof RelationList)) {
$idCondition='"ID" > 0';
}
Just for the sake of satisfying some kind of WHERE clause (as it is referenced in the code below) but that means editing the modules core code, which I want to avoid. Also I assume this has been done on purpose, but I can see no explanation as to what that purpose was.
If it is not required I am happy to make some alterations to remove it and submit a pull request for that.
Can you explain what that code is for?
Kind regards,
HARVS1789UK
Should come up with a better UI for moving rows to another page, right now the pagination arrows are used but its not that obvious what is going on. Maybe larger arrows with text labels on the edges of the grid field something like that?
i have this simple code
class ReviewToplist extends DataObject implements PermissionProvider {
private static $many_many = array(
'ToplistItems' => 'ReviewToplistItem'
);
private static $many_many_extraFields=array(
'ReviewToplistItem'=>array(
'SortOrder'=>'Int'
)
);
public function getCMSFields() {
$fields = parent::getCMSFields();
if( $this->exists() ) {
$config = GridFieldConfig_RelationEditor::create();
$config->getComponentByType('GridFieldAddExistingAutocompleter')->setSearchFields(array('Affiliate.Name'))->setResultsFormat('$Affiliate');
$config->addComponent(new GridFieldSortableRows('SortOrder'));
$gridField =GridField::create( 'ToplistItems', 'ToplistItems', $this->ToplistItems(), $config);
$fields->addFieldToTab("Root.Main", $gridField);
} else {
$fields->addFieldToTab( 'Root.Main', new LiteralField( 'ToplistItemsMessage', '<p>You must Add the toplist before you can add items!</p>' ) );
}
return $fields;
}
public function ToplistItems() {
return $this->getManyManyComponents('ToplistItems')->sort('SortOrder');
}
}
class ReviewToplistItem extends DataObject {
private static $belongs_many_many = array(
'ReviewToplist' => 'ReviewToplist'
);
}
and when i tried to access that in the admin.. it returns an error like this:
ERROR [User Error]: Couldn't run query:
SELECT DISTINCT MAX("SortOrder")
FROM "ReviewToplistItem"
INNER JOIN "ReviewToplist_ToplistItems" ON "ReviewToplist_ToplistItems"."ReviewToplistItemID" = "ReviewToplistItem"."ID"
WHERE ("ReviewToplist_ToplistItems"."ReviewToplistID" = '18')
Column 'SortOrder' in field list is ambiguous
Any idea why? I just followed the documentation for the many_many relationship here
The 'Allow drag and drop re-ordering' check box is checked by default and when trying to uncheck it, it automatically checks itself again.
This is when using SortableGridField in the ModelAdmin.
I had to specifically disable GridFieldPaginator and GridFieldPageCount to prevent the following bug. Notice I am trying to reorder widgets, so I'm not sure if thats the issue.
1 requests ❘ 15.5 KB transferred
Widgets
/........./admin/pages/edit/EditForm/field
515 ms109 ms
HeadersPreviewResponseCookiesTiming
ERROR [Notice]: Object of class GridState_Data could not be converted to int
IN POST /......../admin/pages/edit/EditForm/field/Widgets
Line 137 in /......../framework/forms/gridfield/GridFieldPaginator.php
Source
======
128: $state = $this->getGridPagerState($gridField);
129:
130: // Update item count prior to filter. GridFieldPageCount will rely on this value
131: $this->totalItems = $dataList->count();
132:
133: if(!($dataList instanceof SS_Limitable) || ($dataList instanceof UnsavedRelationList)) {
134: return $dataList;
135: }
136:
* 137: $startRow = $this->itemsPerPage * ($state->currentPage - 1);
138: return $dataList->limit((int)$this->itemsPerPage, (int)$startRow);
139: }
140:
141: /**
142: * Determines arguments to be passed to the template for building this field
143: * @return ArrayData|null If paging is available this will be an ArrayData
Trace
=====
GridFieldPaginator->getManipulatedData(GridField,HasManyList)
GridField.php:222
GridField->getManipulatedList()
GridField.php:264
GridField->FieldHolder()
GridField.php:644
GridField->gridFieldAlterAction(Array,Form,SS_HTTPRequest)
GridField.php:108
GridField->index(SS_HTTPRequest)
RequestHandler.php:278
RequestHandler->handleAction(SS_HTTPRequest,index)
RequestHandler.php:190
RequestHandler->handleRequest(SS_HTTPRequest,DataModel)
GridField.php:749
GridField->handleRequest(SS_HTTPRequest,DataModel)
RequestHandler.php:212
RequestHandler->handleRequest(SS_HTTPRequest,DataModel)
RequestHandler.php:212
RequestHandler->handleRequest(SS_HTTPRequest,DataModel)
Controller.php:153
Controller->handleRequest(SS_HTTPRequest,DataModel)
LeftAndMain.php:438
LeftAndMain->handleRequest(SS_HTTPRequest,DataModel)
AdminRootController.php:89
AdminRootController->handleRequest(SS_HTTPRequest,DataModel)
Director.php:325
Director::handleRequest(SS_HTTPRequest,Session,DataModel)
Director.php:143
Director::direct(/admin/pages/edit/EditForm/field/Widgets,DataModel)
main.php:128
When fixSortColumn() runs with multiple records having a position of 0 duplicate sort indexes will occur when updating the indexes. This works as expected when there is only a single record with an sort index of 0 but begins to fail when there are two or more records with an sort index of 0, this bug was introduced in the chances for #47.
I tried to find this and install by composer with out luck? is there a different name?
I followed this example using Silverstripe 3.1.8: https://github.com/UndefinedOffset/SortableGridField/blob/master/docs/ManyManyExample.md
All I get is the following error:
[User Error] Sort column OrderKey must be an Int, column is of type
GET /admin/pages/edit/show/1
Line 167 in /var/www/default/sortablegridfield/code/forms/GridFieldSortableRows.php
If I manually change the sort order in the DB to something else than 0, it works, but when I add new items to the grid, the value always defaults to 0.
Hi, if i use a has_many relation, than there will always be the editable "SortOrder" field on create a new item or on editing an existing. How can i get rid of it?
page.php
static $has_many = array(
'Zusatzinfos' => 'Zusatzinfos'
);
[...]
// optionale Zuordnung von Zusatzinformationen (Accordeon) je Seite
$zusatzinfosFieldConfig = GridFieldConfig::create()->addComponents(
new GridFieldToolbarHeader(),
new GridFieldAddNewButton('toolbar-header-right'),
new GridFieldSortableHeader(),
new GridFieldDataColumns(),
new GridFieldPaginator(10),
new GridFieldEditButton(),
new GridFieldDeleteAction(),
new GridFieldDetailForm(),
new GridFieldDeleteAction('unlinkrelation'),
new GridFieldSortableRows('SortOrder')
);
$ZusatzinfosField = new GridField("Zusatzinfos", "Zusatzinfos:", $this->Zusatzinfos()->sort('SortOrder'), $zusatzinfosFieldConfig);
$fields->addFieldToTab('Root.Zusatzinfos', $ZusatzinfosField);
zusatzinfos.php
static $db = array (
'Headline' => 'Varchar(100)',
'InfoText' => 'HTMLText',
'SortOrder'=>'Int'
);
public function getCMSFields_forPopup() {
$InfoTextBildField = new UploadField(
$name = 'Bild',
$Title = 'Bild (px * px)'
);
$InfoTextBildField->allowedExtensions = array('jpg', 'png', 'gif');
$InfoTextBildField->setConfig('allowedMaxFileNumber', 5);
$InfoTextBildField->setFolderName('Infotextbilder');
$InfoTextBildField->setConfig('previewMaxWidth', 100);
$InfoTextBildField->setConfig('previewMaxHeight', 100);
$InfoTextBildField->setConfig('autoUpload', true);
return new FieldList(
$InfoTextBildField,
new TextField('Headline', 'Headline'),
new TextareaField('InfoText', 'Text'),
new TreeDropdownField('PagelinkID', 'Bitte eine interne Verlinkung wählen', 'SiteTree', 'ID', 'Title', true)
);
}
Thanks for your advice, Carsten.
When dragging the helper Columns do not maintain the widths of the item being dragged, it would be nice if they did just for the sake of appearance.
hi,
can't seem to get this to work - cms says:
[User Warning] None of these templates can be found in theme '': GridFieldSortableRows.ss
could you provide some information on how/where to install the module?
thanks in advance,
andi
just a minor thing, the sort order is not being updated when deleting records.
even after refreshing the admin panel i'm getting the old id's.
working great otherwise, definitely a must-have!
If a GridField_DataManipulator like GridFieldPaginator is added to the GridFieldConfig before GridFieldSortableRows the limit is set on the data list and not reset by GridFieldSortableRows::fixSortColumn().
https://github.com/UndefinedOffset/SortableGridField/blob/master/code/forms/GridFieldSortableRows.php#L116
This triggers the exception:
https://github.com/silverstripe/sapphire/blob/3.0/model/SQLQuery.php#L1074
Adding the GridFieldPaginator to the GridFieldConfig after GridFieldSortableRows is added seems to work.
Right now, I can't activate the checkbox "Allow drag and drop re-ordering" in the backend and so, I'm not able to drag-and-drop the rows beneath. I'm on SilverStripe 3.2.0 now, but had it also before on 3.1.12. The SortableGridField version I use now is dev-master via Composer.
The html code for the element looks like that:
<input type="checkbox" id="Form_EditForm_Content_Blocks_AllowDragDropCheck" value="1" autocomplete="off" class="no-change-track">
Any ideas on that? Thanks in advance.
Hi
Next code in class BlogEntry extends DataObject:
public static $belongs_many_many_extraFields=array(
'BlogCategorys'=>array(
'SortOrder'=>'Int'
)
);
not created 'SortOrder' column
Problem is solved with the following code:
class BlogCategory extends Page {
private static $many_many = array(
'BlogEntrys' => 'BlogEntry'
);
public static $many_many_extraFields=array(
'BlogEntrys'=>array(
'SortOrder'=>'Int'
)
);
}
class BlogEntry extends DataObject {
private static $belongs_many_many = array(
'BlogCategorys' => 'BlogCategory'
);
public function getCMSFields() {
...
$gridFieldConfig = GridFieldConfig_RelationEditor::create();
$gridFieldConfig->removeComponentsByType('GridFieldAddNewButton');
$gridFieldConfig->addComponent(new GridFieldSortableRows('SortOrder'));
$gridfield = new GridField("BlogCategorys", "Blog Categorys", $this->BlogCategorys(), $gridFieldConfig);
$fields->addFieldToTab('Root.BlogCategorys', $gridfield);
...
}
public function BlogCategorys() {
return $this->getManyManyComponents('BlogCategorys')->sort('SortOrder');
}
}
The problem with this code has been solved.
But why is not working with $belongs_many_many_extraFields ?
Hallo,
im trying to sort many_many related data. Your code works great if I add relation to Page.php directly, but not, if i add the relation to Extension class which is extending Page class... :(
I think many_many_extraFields are not found :(
Regards
Pali
When using the GridFieldManyRelationHandler module https://github.com/simonwelsh/silverstripe-GridFieldRelationHandler on the same GridField, GridFieldSortableRows::fixSortColumn breaks on line 134.
ERROR [User Error]: Sort column SortOrder could not be found in Biography's ancestry.
The problem is occuring because the list being passed in is a DataList and not a ManyManyList, even though it Should be a ManyManyList.
I"m not really sure if this is a problem in SortableGridField or in GridFieldManyRelationHandler, but the error is occuring in code in SortableGridField so I thought I'd start here.
Relevant Code:
$config->addComponent( new GridFieldSortableRows('SortOrder') );
$config->addComponent( new GridFieldManyRelationHandler(), 'GridFieldPaginator' );
Error Report
ERROR [User Error]: Sort column SortOrder could not be found in Biography's ancestry
IN POST /admin/pages/edit/EditForm/field/Biographies
Line 133 in C:\wamp\www\snwp_v31\SortableGridField\code\forms\GridFieldSortableRows.php
Source
======
124: $query->limit(array());
125: return $query;
126: });
127: $many_many = ($list instanceof ManyManyList);
128: if (!$many_many) {
129: $sng=singleton($gridField->getModelClass());
130: $fieldType=$sng->db($this->sortColumn);
131: if(!$fieldType || !($fieldType=='Int' || is_subclass_of('Int', $fieldType))) {
132: if(is_array($fieldType)) {
* 133: user_error('Sort column '.$this->sortColumn.' could not be found in
'.$gridField->getModelClass().'\'s ancestry', E_USER_ERROR);
134: }else {
135: user_error('Sort column '.$this->sortColumn.' must be an Int, column is of type '.$fieldType,
E_USER_ERROR);
136: }
137:
138: exit;
139: }
Trace
=====
user_error(Sort column SortOrder could not be found in Biography's ancestry,256)
GridFieldSortableRows.php:133
GridFieldSortableRows->fixSortColumn(GridField,DataList)
GridFieldSortableRows.php:95
GridFieldSortableRows->getManipulatedData(GridField,DataList)
GridField.php:222
GridField->getManipulatedList()
GridField.php:264
GridField->FieldHolder()
GridField.php:644
GridField->gridFieldAlterAction(Array,Form,SS_HTTPRequest)
GridField.php:108
GridField->index(SS_HTTPRequest)
RequestHandler.php:278
RequestHandler->handleAction(SS_HTTPRequest,index)
RequestHandler.php:190
RequestHandler->handleRequest(SS_HTTPRequest,DataModel)
GridField.php:749
GridField->handleRequest(SS_HTTPRequest,DataModel)
RequestHandler.php:212
RequestHandler->handleRequest(SS_HTTPRequest,DataModel)
RequestHandler.php:212
RequestHandler->handleRequest(SS_HTTPRequest,DataModel)
Controller.php:153
Controller->handleRequest(SS_HTTPRequest,DataModel)
LeftAndMain.php:438
LeftAndMain->handleRequest(SS_HTTPRequest,DataModel)
AdminRootController.php:89
AdminRootController->handleRequest(SS_HTTPRequest,DataModel)
Director.php:325
Director::handleRequest(SS_HTTPRequest,Session,DataModel)
Director.php:143
Director::direct(/admin/pages/edit/EditForm/field/Biographies,DataModel)
main.php:128
Say if Product is a decedent of Page. When you sort them, it updates Product table but not Product_Live.
The version here works as it also updates Live version: https://raw.githubusercontent.com/dnadesign/SortableGridField/a4b51c42b9ecc254212d84324d581e57fb7471ca/code/forms/GridFieldSortableRows.php
But seems the parts which update Live table have been removed in the latest release.
I think it would be good idea to reinstate them because sometimes you need an alternative sort for pages as well, especially when you extend it for Products, Categories etc.
Hi!
The line 183 of the GridFieldSortableRows.php is producing problems:
DB::query('UPDATE "' . $table
. '" SET "' . $sortColumn . '" = ' . $sortColumn = ($max + $i)
. ' WHERE "ID" = '. $obj->ID);
I think it should be:
DB::query('UPDATE "' . $table
. '" SET "' . $sortColumn . '" = ' . ($max + $i)
. ' WHERE "ID" = '. $obj->ID);
Regards,
Jose A.
You specifically limit the module to <3.2
. Does that mean its broken in there? Given its a dependency on many other modules, this limits 3.2 early adoption a bit. Any chance you could check compat?
Hi,
Now that Composer is used to manage packages, it would be helpful if you had some release tags in this repository.
Perhaps even just tagging "head" with 0.1.0?
I am trying to add setAppendToTop to my sortable GridField. However as soon as I add the following
$config->addComponent(GridFieldSortableRows::create('SortOrder')->setAppendToTop(true));
when I access page in the CMS I am getting:
Fatal error: Call to undefined method GridFieldSortableRows::create()
Silverstripe Version 3.1.2
Full code:
class ProductsHolderPage extends Page
{
private static $many_many = array(
'Products' => 'Product'
);
private static $many_many_extraFields=array(
'Products'=>array(
'SortOrder'=>'Int'
)
);
public function Products() {
return $this->getManyManyComponents('Products')->sort('SortOrder');
}
function getCMSFields()
{
$fields = parent::getCMSFields();
$config = GridFieldConfig_RelationEditor::create(10);
$config->getComponentByType('GridFieldAddExistingAutocompleter')->setSearchFields(array('Name'))->setResultsFormat('$Name');
$config->addComponent(new GridFieldSortableRows('SortOrder'));
$config->addComponent(GridFieldSortableRows::create('SortOrder')->setAppendToTop(true));
$productsField = new GridField(
'Products',
'Product',
$this->Products()
,$config
);
$fields->addFieldsToTab('Root.Products', array(
$productsField
));
return $fields;
}
}
Many thanks
Currently the GridFieldSortableRows::fixSortColumn()
method is only called when getManipulatedData()
is called, which means only when the grid is displayed.
But if an user creates a new record and gets redirected to the detail view of the created record, the getManipulatedData()
method never gets called.
This leaves the sorting in an inconsistent state:
If the site uses caching or things like static publishing, it may happen, that in the time between the creation of a record and the view of its grid representation, the frontend renders the sorted list with the wrong order (because fixSortColumn
has not been called until now) and caches this wrong state.
I don't know if there is a clean solution without modifying the SilverStripe core (eg. the GridFieldDetailForm
)?
Need to provide some brief documentation in Readme.md on how to upgrade from Data Object Manager's SortableDataObject to using GridField, mainly that the following SQL needs to be run:
UPDATE Table SET SortOrder=SortOrder+1;
Hi there,
I just noticed a small issue on this great module.
In the case you have an error in the type of field for the sort order field, you should get this message :
Sort column xxxxx must be an Int, column is of type Array (in case the column type is an array).
It happens that the $fieldType variable is not instantiated in all case, because this variable is instantiated in the if (!$many_many) { statement.
To fix this issue, I just moved the $fieldType instantiation upper in the code like below:
This code is from the file SortableGridField/code/forms/GridFieldSortableRows.php at the line 139:
$many_many = ($list instanceof ManyManyList);
if (!$many_many) {
$sng=singleton($gridField->getModelClass()); <------- move this line before the if statement.
$fieldType=$sng->db($this->sortColumn);<------- move this line before the if statement.
if(!$fieldType || !($fieldType=='Int' || is_subclass_of('Int', $fieldType))) {
if(is_array($fieldType)) {
user_error('Sort column '.$this->sortColumn.' could not be found in '.$gridField->getModelClass().''s ancestry', E_USER_ERROR);
}else {
user_error('Sort column '.$this->sortColumn.' must be an Int, column is of type '.$fieldType, E_USER_ERROR);
}
exit;
}
}
As a result, I end up with the following working code:
$sng=singleton($gridField->getModelClass()); <--- this line has been moved up.
$fieldType=$sng->db($this->sortColumn); <--- this line has been moved up.
$many_many = ($list instanceof ManyManyList);
if (!$many_many) {
if(!$fieldType || !($fieldType=='Int' || is_subclass_of('Int', $fieldType))) {
if(is_array($fieldType)) {
user_error('Sort column '.$this->sortColumn.' could not be found in '.$gridField->getModelClass().'\'s ancestry', E_USER_ERROR);
}else {
user_error('Sort column '.$this->sortColumn.' must be an Int, column is of type '.$fieldType, E_USER_ERROR);
}
exit;
}
}
In case this is something you are willing to put this into a future release of your great module.
Cheers,
Youss
TestObject.php
'Text', 'SortOrder'=>'Int' ); ``` private static $has_one = array( 'DedicatedTo' => 'Page' ); private static $default_sort='SortOrder'; ``` } PageSidebar.php 'TheTestObject' ); public function getCMSFields() { $fields = parent::getCMSFields(); $conf=GridFieldConfig_RelationEditor::create(10); $conf->addComponent(new GridFieldSortableRows('SortOrder')); $fields->addFieldToTab('Root.TestObjects', new GridField('TestObjects', 'TestObjects', $this->TestObjects(), $conf)); return $fields; } ``` } NO PHP Issues When trying to Drag&Drop it just selects the Text. Checking "Allow Drag&Drop" does not change anything. Clicking "Sorttoggle" does not change anything. ![image](https://f.cloud.github.com/assets/4111685/2011789/d0b1393a-877f-11e3-83c9-4d916f0af987.png)Looks like there maybe an issue with duplicate column names, we should ensure we're targeting the right table. http://stackoverflow.com/questions/17226300/sortablegridfield-causing-sql-error/20985634#20985634
GridFieldSortableRows would seem to automatically overwrite the contents of every field in each row incrementally, as soon as it's added, if it's non-numeric. I unwittingly added the component to the wrong field, and ended up having to restore from a database backup, because it overwrote my Text column with integer values.
Lots of SilverStripe 2.4 installations rely on SortableDataObject for sorting (which comes bundled with Uncle Cheese's DataObjectManager).
Unfortunately, the SortOrder field as managed by SortableDataObject will always start at '0', which will be 'fixed' by SortableGridField using the 'fixSortColumn' method, so the item that was on top before will now be moved to the end of the list.
One can easily get around this by running 'UPDATE SortedTable SET SortOrder = SortOrder + 1' on the tables in question, but imho it would make more sense to leave all items (including the '0' one) at their position?
I've translated module a few months ago on Transifex but it hasn't been included yet.
Can you please add it? Thanx :)
My gridfield span multiple pages, is there a way to drag-and-drop an item to the next page?
In the function getManipulatedData, I moved the call to fixSortColumn to the front, because it doen't always run properly otherwise.
No idea if this is the best solution, though.
/**
* Manipulate the datalist as needed by this grid modifier.
* @param GridField $gridField Grid Field Reference
* @param SS_List $dataList Data List to adjust
* @return DataList Modified Data List
*/
public function getManipulatedData(GridField $gridField, SS_List $dataList) {
$this->fixSortColumn($gridField, $dataList);
$headerState = $gridField->State->GridFieldSortableHeader;
$state = $gridField->State->GridFieldSortableRows;
if ((!is_bool($state->sortableToggle) || $state->sortableToggle==false) && $headerState && !empty($headerState->SortColumn)) {
return $dataList;
}
if ($state->sortableToggle == true) {
$gridField->getConfig()->removeComponentsByType('GridFieldFilterHeader');
$gridField->getConfig()->removeComponentsByType('GridFieldSortableHeader');
}
//Detect and correct items with a sort column value of 0 (push to bottom)
return $dataList->sort($this->sortColumn);
}
Sorting on has_many relationships could be optimized with raw SQL instead of using DataObject->write(). How ever will need to have away to find what table the sort column appears on since it could be defined on a parent DataObject from the object the GridField is receiving.
Hi!
To make some operations I need to detect that the user has changed the lines order.
The event should indicate the ID's and classname in which changes have occurred.
The event could be defined in the current controller.
$controller = Controller::curr();
&controller->onBeforeChangeSort(...)
Thank you for this wonderful module.
Jose A.
Is there any chance to tell SortableGridField to sort the Dataobjects in reverse order? In my case i have told the Dataobject: $defaultSort = "SortOrder DESC" which displays the normal grid in reversed order (newest first)
But when i click on "sort" the order is vice versa (ASC) which is confusing.
Currently there is no visual feedback when a user sorts a GridField row. As a user it would be nice to see a small loading indicator on the affected row when sorting is underway, then disappear once the ajax request is successful.
We should change the install instructions to prefer composer over manual installs by now most users are using composer for installs anyways.
Hi,
moving an item to next page doesn't work well in Firefox 20.0.1.
The next page arrow blinks but the item gets sorted somewhere on the current page.
Even making the button bigger (with firebug) doesn't work.
In IE9 it works
I run SS 3.0.5 and latest verion of SortableGridField
Silverstripe 3.0.5:
When trying to drag and drop items in gridfield...
ERROR [Notice]: Object of class GridState_Data could not be converted to int
IN POST .../admin/pages/edit/EditForm/field/Event
Line 137 in ...\framework\forms\gridfield\GridFieldPaginator.php
Config using GridFieldConfig_RecordEditor
Any ideas?
I see you have a .settings, .project and .buildpath
I know it can be useful to share the IDE configs so contributors can use your coding formatter settings, but it just doesn't belong here.
If you want to share the config you should put a link in the readme or so
Hey,
I just saw that GridFieldSortableRows
uses plain SQL to update the sortColumn which makes it a bit difficult to use it with the partical cache and aggregates like <% cached 'sortablelist', List(SortableObject).max(LastEdited) %>
.
As the sortColumn doesn't reflect a relation lastEdited
should be updated.
What do you think?
Hi,
I've noticed that a click on the "Allow drag/drop" checkbox adds the class 'changed' on the form (via jquery.changetracker.js). This can be prevented by adding the class 'no-change-track' to the checkbox (in GridFieldSortableRows.ss, LeftAndMain.EditForm.js setsup jquery.changetracker.js to ignore fields with this class).
I'm using it with ModelAdmin right now to make the list ('searchresults') sortable. When I click away from the current model listview to another after sorting, I get the popup that my form wasn't saved.
Greetings and keep up the good work!
Hi,
Just wanted to let you know
I succesfully created a nested gridfield in ss3.0.3.
(Page hasmany rows, Row hasmany columns)
However, the same code doesn't seem to work in SS3.1 beta
Page with rows works, but after adding the column object to it, i can't creat another row anymore (fields don't show up).
Of course... 3.1 is still beta...
Need to add a note to readme for many_many relations about the field name having to match the relationship name exactly in order for the field to work correctly. See issue #63 for more info and the reasoning for this.
I am testing very latest Framework and CMS with conjunction of SortableGridField (Good work anyway! 👍) and when I click on Drag&Drop button - GridField disappear.
I have from:
This:
Is this issue SortableGridField related? I tried debug JavaScript but found nothing indicating any problem. entwine onchange populate data and call reload, after that GridField disappear...
Tested on Mac & Windows under all major browsers (Safari, Firefox, Chrome, IE)
Any help will be appreciated.
Thanks
Tomas
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.