SSbits - Home page
Site by Carbon Crayon
Submit a Post >

Tutorials - Big bits of code to help you do more

Dynamically Generating Dropdown Lists

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');
	}
}
Aram Balakjian avatar

Aram Balakjian

Aram is a web developer running London based agency Aab Web. He has a strong passion for developing attractive, usable sites around the SilverStripe CMS.

  • Daniel Hensby
    13/10/2010 10:32am (4 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 (4 years ago)

    Good spot, thanks Dan!

  • Chris Hope
    17/11/2010 8:23am (3 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 (3 years ago)

    Hi,

    is there any trick to make Sortable Enum like the one in ImageGallery.

    Thanks

  • Pete
    23/10/2011 3:50pm (2 years 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 (2 years 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',

  • sjdeere
    04/01/2013 2:12pm (1 year ago)

    This tutorial is just what i needed

    What if i wanted to show a thumbnail image?
    function DropdownSummary()
    {
    $String = $this->Title . ' running on ' . $this->bannerimage()->ThumbBannerImage().'';

    return $String;
    }

    i just get Image_Cached


    I'm generating a list of checkboxs... and rather than titile i'm wondering if its possible to show an image.

  • Aram Balakjian
    04/01/2013 5:08pm (1 year ago)

    Hi Sjdeere,

    I'm not sure, as I havent ever tried to do an HTML summary. You could try explicitly defining the HTML first, like '<img src="' . $this->bannerimage()->URL . '" />' or similar andsee if it renders it?

    Aram

  • moniuch
    13/04/2014 9:19pm (5 days ago)

    Correct me if I'm wrong (I'm a beginner) but the search function (available when you have 20+ items) switches from 'contains' mode to 'starts with' mode when you customize the display values with DropdownSummary(). At least this is what happens here. v.3.1.3

Post a comment ...

You cannot post comments until you have logged in. Login Here.

Advertisement

Site of the Month

Find SSbits on

Top Contributers

Rank Avatar Name
1 article image Aram Balakjian
2 article image Daniel Hensby
3 article image Marcus Dalgren
4 article image Hamish Campbell
5 article image Ty Barho
6 article image njorndare
7 article image Martijn van Nieuwenhoven
8 article image Darren-Lee
9 article image Roman Schmid
10 article image Matt Clegg

View full leaderboard


Advertisement