Tutorials - Big bits of code to help you do more
Dynamically Generating Dropdown Lists
Tweet13 October 2010 | | | Supports v2.4, v2.3
This post title may look familiar, but it has in fact been completely re-written with lots of new code! When using dropdown menus, you will often want to dynamically generate the options, usually to a list of DataObjects or Pages for the user to choose from. This tutorial explores the options at your disposal when it comes to creating dynamic dropdowns in the SilverStripe.
From Enum Values
Alternatively you can generate the list from a set of Enum values defined in your $db array like so:
"Options" => "Enum('Default, Option1, Option2, Option3', 'Default')"
Then use this syntax when adding your form field to the getCMSFields() function:
$fields->addFieldToTab(
"Root.Content.Main",
new DropdownField(
'Options',
'Choose an option',
$this->dbObject('Options')->enumValues())
);
From DataObjects
The Quick way
If you want to create a drop down list (or option set) dynamically, for example from a set of pages or DataObjects, you can use the DataObject::get() call along with the function toDropdownMap() to generate it like so:
new DropdownField(
'DataObjectID',
'Please choose an object',
Dataobject::get("MyObject")->map("ID", "Title", "Please Select")
);
We use the map() function to generate a key => Value array, with the ID as the Key which is what will be saved) and the Title field as the value (which is what will be displayed). The downside to this method is that if there are no MyObject objects you will get a big far error.
The Longer (more stable) way
In order to prevent the error above you can instead create a function which will either return the mapped values or an array containing a 'None Found' type message. That function might look something like this:
function getMyObjectOptions()
{
if($Pages = DataObject::get('MyObject'))
{
return $Pages->map('ID', 'Title', 'Please Select');
}
else
{
return array('No Objects found');
}
}
Then in your Dropdown definition you just add $this->getMyObjectOptions() as the $Source argument:
new DropdownField( 'DataObjectID', 'Please choose an object', $this->getMyObjectOptions() );
Adding custom 'Summary' values
Let's say you wanted your dropdown options to say something like 'MyObjectTitle running on 23/3/2010'. Well that is pretty simple actually, all you need to do is create a function inside MyObject which returns the string that you want. So for example let's assume that the MyObject DataObject has a field Title and a field Date, here is the function you would add to MyObject.php
function DropdownSummary()
{
$String = $this->Title . ' running on ' $this->dbObject('Date')->Nice();
return $String;
}
Then in our getMyObjectOptions() function we simply specify DropdownSummary in the map() function instead of Title
function getMyObjectOptions()
{
if($Pages = DataObject::get('MyObject'))
{
return $Pages->map('ID', 'DropdownSummary', 'Please Select');
}
else
{
return array('No Objects found');
}
}
6 Comments
RSS feed for comments on this page RSS feed for all comments
Daniel Hensby
13/10/2010 10:32am (2 years ago)
Hey Aram,
For the enumValues, if you are trying to access the dbObject of the class you're currently in, you can just use $this instead of singleton('ThisPageType'). You only need to use the singleton if its a different object, ie: singleton('SomeOtherPageType')
Some pretty sweet tactics in there, though.
Aram Balakjian
14/10/2010 11:53am (2 years ago)
Good spot, thanks Dan!
Chris Hope
17/11/2010 8:23am (2 years ago)
Could you repost the singleton version as well? There are times when you do need to use it to get the values from a different object. Thanks!
Mom Bunheng
05/07/2011 1:28pm (11 months ago)
Hi,
is there any trick to make Sortable Enum like the one in ImageGallery.
Thanks
Pete
23/10/2011 3:50pm (7 months ago)
Hi Aram,
I'm trying to add the enum Values method to page.php but can't get it to show up in cms editor panels.
My aim is to create a dropdown that would appear on every page type (in edit mode) so an editor can pick a class that will then be added to the <body> tag.
Where in page.php would I add "Then use this syntax when adding your form field to the getCMSFields() function:" ?
Is there a better method, i'm new to SS and a little overwhelmed!
borriej
27/12/2011 3:05pm (5 months ago)
How do you make a dependant dropdown menu on the front-end?
i have a bookingsform:
- first dropdown menu returns a DataObject. Titles of pages can be selected.
- Now a secondary dropdown menu must be filled with possible dates/prices, which are stored in the public static db array.
How do i do this?
my first dropdown is generated by:
public function getMyTours(){
$today = date('Y-m-d');
if($Pages = DataObject::get("Tour", "EndDate >= '$today'","StartDate", "", "" )){
return $Pages->map('Title', 'Title', 'Please Select');
}else{
return array('No Tours found');
}
}
........................
new DropdownField(
'TourProgram',
'Select a trip',
$this->getMyTours()
),
........................
Dates and prices are stored inside each page in:
public static $db = array(
'DatesPricesA' => 'Text', /* contains the periode */
'DatesPricesB' => 'Text',
'DatesPricesC' => 'Text',
'DatesPricesD' => 'Text',
'DatesPricesE' => 'Text',
'DatesPricesAPrice' => 'Text', /* contains the price */
'DatesPricesBPrice' => 'Text',
'DatesPricesCPrice' => 'Text',
'DatesPricesDPrice' => 'Text',
'DatesPricesEPrice' => 'Text',
Post a comment ...
You cannot post comments until you have logged in. Login Here.