Dynamically set values of objects added via Silverstripe GridField (CMS) - php

I have a basic relation editor GridField, and I need to dynamically define/set the value of any objects added via that GridField, with data related to the GridField's context.
class Draw extends DataObject {
private static $has_many = array(
'Items' => 'Item'
);
}
When an Item is added via Draw's Items GridField, I need to define a value for use in Item::getCMSFields()

Some good suggestions in here: https://www.silverstripe.org/community/forums/data-model-questions/show/21517?start=7
You can work directly with the GridField's GridFieldDetailForm component, and set fields accordingly.
The code that worked for me is:
$config = GridFieldConfig_RecordEditor::create();
if($this->exists()) {
// Ensure that fields are generated with knowledge of the parent
$editComponent = $config->getComponentByType('GridFieldDetailForm');
$item = new Item();
$item->DrawID = $this->ID;
$editComponent->setFields($item->getCMSFields());
}
$items = new GridField('Items', 'Items', $this->Items(), $config);
$fields->addFieldToTab('Root.Main', $items);
You can then call Draw::get()->byID($this->DrawID) from Item::getCMSFields()

Related

How to change order of items in SilverStripe GridField

I use a GridField in SilverStripe to create HTML section items that are rendered on a page. This works so far but it always displays the sections in the order that I added them to the CMS or rather by the ID it gets when it's created.
So my question is: How can i change that order. I don't want to manually change the IDs but would rather do a simple drag and drop.
Edit: Could the use of Elemental be a solution to this problem?
Screenshot of the CMS view
The Page:
class HomePage extends Page
{
private static $has_many = [
'SectionObjects' => SectionObject::class
];
public function getCMSFields()
{
$fields = parent::getCMSFields();
$fields->addFieldToTab('Root.Sections',
$grid = GridField::create('SectionObjects', 'Sections', $this->SectionObjects(), GridFieldConfig_RecordEditor::create())
);
$config = $grid->getConfig();
$dataColumns = $config->getComponentByType(GridFieldDataColumns::class);
$dataColumns->setDisplayFields([
'ID' => 'ID',
'LastEdited' => 'Changed'
]);
return $fields;
}
}
The Section object
class SectionObject extends DataObject{
private static $db = [
'Content' => 'Text',
'BgColor' => Color::class
];
private static $has_one = [
'HomePage' => HomePage::class
];
public function getCMSFields(){
return new FieldList(
TextareaField::create('Content','SectionContent'),
ColorField::create('BgColor', 'Hintergrundfarbe')
);
}
}
Definitely using the elemental module would allow you to have the kind of behaviour you want - but if you don't want to go to the effort of refactoring your code to comply with that module, you could use either the gridfieldextensions or sortablegridfield module to allow you to sort the gridfield (with drag and drop) to your heart's content.

silverstripe-translatable: how to make dataobjects translatable (slideshow)?

I am creating a multilingual Website in Silverstripe, the goal is to have the whole content available in three languages. I am using the translatable module, works fine for now.
Some pages contains a slideshow, meaning that I am associating a bunch of images and captions to these pages. Looks like this:
class Slide extends DataObject {
private static $db = array(
'Caption' => 'Varchar(255)',
'SortIndex' => 'Int'
);
private static $has_one = array(
'ParentPage' => 'Page',
'Image' => 'Image'
);
public static $default_sort = 'SortIndex';
public function getCMSFields() {
// parent::getCMSFields() does all the hard work and creates the fields for Title, IsActive and Content.
$fields = parent::getCMSFields();
$fields->dataFieldByName('Caption')->setTitle('Titel');
$fields->dataFieldByName('Image')->setTitle('Bild');
$fields->dataFieldByName('Index')->setTitle('Reihenfolge');
$fields->push(new TextField('Caption', 'Titel'));
$fields->push(new UploadField('Image', 'Profile Image'));
// Apply Translatable modifications
$this->applyTranslatableFieldsUpdate($fields, 'updateCMSFields');
return $fields;
}
}
class SlideShowPage extends Page {
private static $has_many = array(
'Slides' => 'Slide'
);
public function getCMSFields() {
$fields = parent::getCMSFields();
$conf = GridFieldConfig_RelationEditor::create(10);
$conf->addComponent(new GridFieldSortableRows('SortIndex'));
$fields->addFieldToTab('Root.Slideshow', new GridField('Slide', 'Slides', $this->Slides(), $conf));
// Apply Translatable modifications
$this->applyTranslatableFieldsUpdate($fields, 'updateCMSFields');
return $fields;
}
}
I want to make these slideshows translatable as well. Meaning that I want to prepare the slide show once in the primary language, then hit the "create new translation" button, and get the slideshow available in the translated version as well, with the captions ready to be translated (similar as the main text content). According to the silverstripe-translatable docs this shall be possible. I have added these calls to applyTranslatableFieldsUpdate() (see in the code above) and added these lines to my _config.php file as well:
SlideShowPage::add_extension('Translatable');
Slide::add_extension('Translatable');
The table Slide_translationgroups is even created successfully and filled with new entries for each translation. But the content of table Slide is not copied.
What am I missing?
Thanks!
Sacher

Custom Silverstripe Meta Field not saving

I created a Meta Title using the code below but it works for majority of my websites but one particular website will not save the the Meta Title so when I edit it shows my previously entered title, same code for all websites but one is not saving?
class Page extends SiteTree {
private static $db = array(
'MetaTitle' => 'Varchar(255)'
);
private static $has_one = array(
);
public function getCMSFields() {
$fields = parent::getCMSFields();
$fields->addFieldToTab('Root.Main', TextField::create('MetaTitle')
->setRightTitle('Shown at the top of the browser window and used as the "linked text" by search engines.')
->addExtraClass('help')
, 'MetaDescription');
return $fields;
}
}
If you do not /dev/build after adding a new $db property, changes will not save properly.

How to add Custom button and its functionality in Admin Silverstripe?

How to add Custom button and its functionality in Admin Silverstripe?
Please tell me solution.
Custom Button add only in one menu.
Like #wmk mentioned in the comments, you can just take the framework code for GridFieldPrintButton as a base and go from there. SilverStripe also have a basic tutorial for creating a custom ActionProvider.
Rather than rehash the tutorial here, I will provide you a very basic custom action provider that you can copy and extend to do what you need. While you don't note the exact result you are wanting from the button, I will provide just a very generic class.
This code is a stripped down version of the GridFieldPrintButton that #wmk mentioned. It supports both the button itself invoking the custom code as well as the URL.
I've noted in the code a reference that I have kept to "grid-print-button", this is to make your button sit nicely next to the print rather than likely sitting on another line (as it did in my testing on an older 3.1 site I built).
class GridFieldCustomButton implements GridField_HTMLProvider, GridField_ActionProvider, GridField_URLHandler {
protected $targetFragment;
protected $someCustomConstructData;
//TargetFragment is just for positioning control of the HTML fragment
//SomeCustomConstructData is just an example of providing some default options into your butotn
public function __construct($targetFragment = "after", $someCustomConstructData = null) {
$this->targetFragment = $targetFragment;
$this->someCustomConstructData = $someCustomConstructData;
}
//Generate the HTML fragment for the GridField
public function getHTMLFragments($gridField) {
$button = new GridField_FormAction(
$gridField,
'custom',
'Custom Action',
'custom',
null
);
return array(
//Note: "grid-print-button" is used here to match the styling of the buttons in ModelAdmin
$this->targetFragment => '<p class="grid-print-button">' . $button->Field() . '</p>',
);
}
public function getActions($gridField) {
return array('myCustomAction');
}
public function handleAction(GridField $gridField, $actionName, $arguments, $data) {
if($actionName == 'myCustomAction') {
return $this->handleMyCustomAction();
}
}
//For accessing the custom action from the URL
public function getURLHandlers($gridField) {
return array(
'myCustomAction' => 'handleMyCustomAction',
);
}
//Handle the custom action, for both the action button and the URL
public function handleMyCustomAction($gridField, $request = null) {
//Do your stuff here!
}
}
Continuing on from the discussion in the comments, you will need to modify your custom ModelAdmin to add new components to its GridField.
class MyCustomAdmin extends ModelAdmin
{
private static $managed_models = array(
'MyCustomObject'
);
private static $url_segment = 'custom-admin';
private static $menu_title = 'All Custom Objects';
public function getEditForm($ID = null, $Fields = null)
{
$form = parent::getEditForm($ID, $Fields);
$fields = $form->Fields();
$gridField = $fields->fieldByName('MyCustomObject');
$gridFieldConfig = $gridField->getConfig();
$gridFieldConfig->addComponent(new GridFieldCustomButton());
return $form;
}
}
Specifically, the line $gridFieldConfig->addComponent(new GridFieldCustomButton()) does the work, taking your custom button as I have shown above and added it to the ModelAdmin. You can also specify where it should go in the GridField too by providing "buttons-before-left" as the first argument in the GridFieldCustomButton constructor.
eg. $gridFieldConfig->addComponent(new GridFieldCustomButton("buttons-before-left"))
More information regarding GridField fragments can be found in the SilverStripe developer documentation.

How to dynamically populate list box from database?

How to dynamically populate list box from database?
Please Provide some examples in zend framework.
Say if you have a table called Test and a corresponding model for it named Test,
class Test extends Zend_Db_Table {
protected $_name = "Test";
function getLisItems() {
$select = $this->getAdapter()->select()->from($this->_name, array(
'key' => 'column1_key',
'value' => 'column2_value'
));
return $this->getAdapter()->fetchPairs($select);
}
}
In your controller action or view, have the following code.
$t = new Test();
$list = new Zend_Form_Element_Select('list');
$list->setLabel('Select your item: ')
->addMultiOptions($t->getLisItems());
Now your list box will be populated with items from the database.

Categories