I am new to silverstripe framework and trying to fetch a list of menu in the admin panel.
I found lots of example to show menu on front-end by Menu(1) and Menu(2) etc. but did not get any sample code to fetch same menu array in admin model.
The code I tried is:
public function getCMSfields() {
$fields = FieldList::create(TabSet::create('Root'));
$fields->addFieldsToTab('Root.Main', array(
TextField::create('Name'),
DropdownField::create('URL')
->setSource(SiteTree::get()),
));
return $fields;
}
ModelAdmin is mainly there to manage DataObjects and not Pages. Have a look at the Docs and this Lesson to learn more about ModelAdmin.
But if you want to manage pages in a ModelAdmin, you could do it like that
class MyPageAdmin extends ModelAdmin {
...
...
private static $managed_models = array(
'Page'
);
public function getList() {
$list = parent::getList();
if($this->modelClass == 'Page'){
$list = $list->filter('ParentID', '1');
}
return $list;
}
}
To manage only children from a specific page, use the getList() function and filter your list after your needs.
There is also (albiet for an older version) this tutorial http://www.ssbits.com/tutorials/2010/dataobjects-as-pages-part-2-using-model-admin-and-url-segments-to-create-a-product-catalogue/ from ssbits
Related
I'm trying to use a GridField component for the first time.
I've added an 'Add' button using GridFieldConfig_RecordEditor as followings:
class AdvertisersPage extends Page
{
//...
public function getCMSFields()
{
$fields = parent::getCMSFields();
$advertiserAccounts = AdvertiserAccount::get();
$fields->addFieldToTab('Root.Advertisers',
$gridField = new GridField(
'Advertisers',
'All advertisers',
$this->Advertisers(),
GridFieldConfig_RecordEditor::create()
)
);
return $fields;
}
}
But the button doesn't do anything besides changing the URL in the browser from
admin/pages/edit/show/7
to
admin/pages/edit/EditForm/7/field/Advertisers/item/new
Here is the related DataObject class:
class AdvertiserAccount extends DataObject
{
//...
private static $has_one = [
'AdvertisersPage' => AdvertisersPage::class,
];
public function getCMSFields()
{
$fields = FieldList::create(
TextField::create('contactNumber'),
TextField::create('nickname')
);
return $fields;
}
}
I need your advice on what should I look at to fix the issue.
It is an extremely strange bug.
I've made some experiments and renamed the related classes. I found that the problem only appears when first GridField constructor parameter name is one of the followings: 'Adv', 'Advert', 'Advertise', 'Advertiser' and 'Advertisers'. In the project, I haven't got any classes with such names. Full-text search through all the project's files hasn't gave any results.
So, I've solved the problem just by renaming the parameter, but what was that?
My goal is it to add a custom FormAction to a DataObjects EditForm inside a ModelAdmin, next to the "Save" and "Delete" action.
The setup:
With updateCMSActions I can add that button.
class MyActionEventExtension extends DataExtension {
public function updateCMSActions(FieldList $actions) {
if($this->owner->canEdit(Member::currentUser())) {
$actions->push(FormAction::create('doMyAction', 'Action'));
}
return $actions;
}
}
This works perfectly fine.
Following this answer on stackoverflow I created a LeftAndMainExtension for the actions handler.
class MyActionLeftAndMainExtension extends LeftAndMainExtension {
private static $allowed_actions = array(
'doMyAction'
);
public function doMyAction($data, $form) {
// Do stuff.
// ... I never get here.
// Return stuff
$this->owner->response->addHeader(
'X-Status',
rawurlencode('Success message!')
);
return $this->owner->getResponseNegotiator()
->respond($this->owner->request);
}
}
The corresponding config.yml file looks like this:
LeftAndMain:
extensions:
- MyActionLeftAndMainExtension
TheDataObject:
extensions:
- MyActionEventExtension
The Problem:
When I click the button, the response gives me "404 Not Found".
The requested URL always is the same:
http://localhost/admin/model-admin-url-slug/TheDataObject/EditForm/field/TheDataObject/item/878/ItemEditForm
Some other solutions I found, suggested to extend the ModelAdmins GridField. This sadly is not an option, since the DataObject I need that action for has alot of relations, which means, it's EditForm also appears in other DataObjects EditForms (nested).
I'm really running out of ideas. Did I miss something within my ModelAdmin? The one I created only implements the basic static vars, so I didn't posted it here.
Any help would be great!
Update:
I ended up, providing a getEditForm method on my ModelAdmin.
public function getEditForm($id = null, $fields = null) {
$form = parent::getEditForm($id, $fields);
$listField = $form->Fields()->fieldByName($this->modelClass);
if ($gridField = $listField->getConfig()->getComponentByType('GridFieldDetailForm')) {
$gridField->setItemRequestClass('MyAdminForm_ItemRequest');
}
return $form;
}
and extending the GridFieldDetailForm_ItemRequest:
class MyAdminForm_ItemRequest extends GridFieldDetailForm_ItemRequest {
private static $allowed_actions = array (
'edit',
'view',
'ItemEditForm'
);
public function ItemEditForm() {
$form = parent::ItemEditForm();
$formActions = $form->Actions();
// Adds all FormActions provided by the model's `getCMSActions` callback
if ($actions = $this->record->getCMSActions()) {
foreach ($actions as $action) {
$formActions->push($action);
}
}
return $form;
}
public function doAction($data, $form) {
// do stuff here
}
}
Sadly this doesn't add an action on has_many or many_many relation gridfields.. and because of that, I'll leave the question opened and unanswered. Maybe sometime there will be a better solution.. :)
One very simple answer to this question (if it's an option for you) is to use the Better Buttons module: https://github.com/unclecheese/silverstripe-gridfield-betterbuttons#creating-a-custom-action
It lets you define the actions on the model, which is a bit questionable from an architecture standpoint, but also works pretty well in the context of Silverstripe and ModelAdmin.
I installed and configured SilverStripe on my server. I installed the MultiForm module and followed the instructions in the module documentation.
After following the instructions I still don't see any new page type in my CMS Portal.
I also tried db/build?flush=1 & dev/build?flush=1 but it doesn't make a difference.
I Created the Following files in mysite/code/ directory
SponsorSignupForms.php
class SponsorSignupForms extends MultiForm{
protected static $start_step = 'CompanyDetailsStep';
}
CompanyDetailsStep.php
class CompanyDetailsStep extends MultiFormStep{
public static $next_steps = 'ContactDetailsStep';
function getFields()
{
$fields = singleton('Member')->getFrontendFields();
return $fields;
}
function getValidator()
{
return new Member_Validator('FirstName', 'Surname', 'Email', 'Password');
}
}
ContactDetailsStep.php
class ContactDetailsStep extends MultiFormStep{
public static $is_final_step = true;
function getFields()
{
$fields = singleton('Reference')->getFrontendFields();
return $fields;
}
}
How do I get these custom MultiForms working and appearing as creatable pages?
Of course you don't see any new page type in the list of available pages, you will only see subclasses of SiteTree there, MultiFormStep is "just" a subclass of DataObject.
You can plug your form to every page you want manually, but you also can create a new page type for your form and include the Form in your Controller and Template, see readme of MultiForm:
class MyFormPage extends Page
{
}
class MyFormPageController extends Page_Controller
{
//
private static $allowed_actions = array(
'SponsorSignupForms',
'finished'
);
public function SponsorSignupForms() {
return new SponsorSignupForms($this, 'Form');
}
public function finished() {
return array(
'Title' => 'Thank you for your submission',
'Content' => '<p>You have successfully submitted the form!</p>'
);
}
}
In the template just include the form:
<% if $SponsorSignupForms %>
$SponsorSignupForms
<% end_if %>
and you should see the form now.
I'm trying to create a custom button that clones a DataObject using the unclecheese/betterbuttons v.1.2 module.
Everything is working fine but at the end I would like to redirect the user to the newly created DataObject edit page instead of refresh/go back. How can I do this?
Here is my custom button code:
class GridFieldCloneBetterButton extends DataExtension {
private static $better_buttons_actions = array(
'clone_do'
);
public function updateBetterButtonsActions($actions) {
$actions->push(
BetterButtonCustomAction::create('clone_do', 'Clone')
->setSuccessMessage('Object cloned')
->setRedirectType(BetterButtonCustomAction::GOBACK)
);
return $actions;
}
public function clone_do() {
$current_record = $this->owner;
$clone = $this->owner->duplicate();
}
}
Maybe if I can access GridFieldDetailForm_ItemRequest from inside the DataExtension I can make this work, but I really don't know how to do it.
I am trying to use TreeMultiselectField to associate many pages to one page in Silverstripe. I was able to do that, the CMS saves them. But now I need to be able to display the pages I selected on the template. How do I do that?
Here's my code so far
class FundsAndPerformancePage extends Page {
public static $many_many = array(
"Funds" => "SiteTree",
"Information" => "SiteTree"
);
public function getCMSFields() {
$fields = parent::getCMSFields();
$fields->addFieldToTab('Root.Main', new TreeMultiselectField('Funds','Select pages for section "Our Funds"', 'SiteTree'));
$fields->addFieldToTab('Root.Main', new TreeMultiselectField('Information','Select pages for section "More Information"', 'SiteTree'));
return $fields;
}
public function Funds(){
//Need to return an array of pages selected with TreeMultiselectField
}
}
class FundsAndPerformancePage_Controller extends Page_Controller {
}
if you want to loop the related Pages in a template, you don't have to define a getter method yourself.
<% loop $Funds %> should work by default, by using the default (magic) getter method ->Funds()
If you need an array anyway, you could do something like this:
public function FundsAsArray(){
return $this->Funds()->toArray();
}
as the getter method returns an instance of ManyManyList, which would have an toArray method inherited from DataList
see http://api.silverstripe.org/3.0/source-class-DataList.html#_toArray