Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

We've moved the forum!

Please use forum.silverstripe.org for any new questions (announcement).
The forum archive will stick around, but will be read only.

You can also use our Slack channel or StackOverflow to ask for help.
Check out our community overview for more options to contribute.

Archive /

Our old forums are still available as a read-only archive.

Moderators: martimiz, Sean, Ed, biapar, Willr, Ingo

Conditional CMS fields


Go to End


5 Posts   6185 Views

Avatar
Anatol

126 Posts

20 August 2008 at 5:20pm

Hi,

is there any (built-in) way to show/hide fields in the CMS backend depending if e.g. a checkbox was checked. A simple CSS "display: none;" to "display: inline;" switch would already be enough.

I am extending the blog entry page type and add a checkbox that can define the entry as an event ("This is an event": check/uncheck). Ideally if it is an event additional fields would appear, e.g. event name, start and end date and time, location, and possibly a link to Google Maps or an embedded map).

An alternative would be to simply add another tab to the page type, something like:

$fields->addFieldToTab("Root.Content.EventInfo", new TextField('Name'));
$fields->addFieldToTab("Root.Content.EventInfo", new CalendarDateField('StartDate'));
etc ...

and add the event infos there. Nice, but it's not as obvious if an entry is an event or not.

Well, I guess my question is simply: Can I hide/reveal CMS fields conditionally?

Cheers!
Anatol

Avatar
ajshort

Community Member, 244 Posts

20 August 2008 at 6:03pm

Hey Anatol,

Out of the box, I dont believe there is a way to create something like

new ConditionalField(...

However, it is quite simple to add this functionality. For example, the forum module uses a few lines of custom JS to only display group context fields if a group radio button is checked. It would be quite simple to adapt this for your own uses.

If you look at http://svn.silverstripe.com/open/modules/forum/trunk/code/Forum.php - the function getCMSFields() bit, youll notice that it requires the custom JS file - http://svn.silverstripe.com/open/modules/forum/trunk/javascript/ForumAccess.js

If you took that code, and adapted it slightly it should work. For example, if you had a field called "Events" that when checked would display "Events_Text", you could use something like:

Behaviour.register({
	'#Form_EditForm_Events': {
		onclick: function() {
			if(this.checked) $('Form_EditForm_Events_Text').style.display = 'block';
			else $('Form_EditForm_Events_Text'.style.display) = 'none';
		},
		initialize: function() {
			this.onclick();
		}
	},
});

Avatar
Anatol

126 Posts

21 August 2008 at 6:34am

Hi,

Thank you very much! I will try this (but I may actually stick to my alternative way and simply create an additional tab for the event info). I am sure your solution will come in handy sooner or later, though.

Cheers!
Anatol

Avatar
Anatol

126 Posts

27 August 2008 at 11:52am

Edited: 27/08/2008 11:58am

Hi ajshort,

I tried using Javascript "Behaviour.register" as you suggested and it works perfectly. It's much more flexible than any built-in conditional CMS field would be. I still stick to my solution to add an additional tab to the Content fieldset, but I could use "Bevaviour.register" for a number of other things (e.g. update the initial event name based on the value in the page title field and to create a set of predefined locations). See an example below.

If anyone needs more details about it, this is what I did to add event details to my blog entries. It's just an example which I hope may help someone who is new to extending the Silverstripe CMS:

1. Creating additional database fields
I added event details to the BlogEntry Page Type, but it can be added to any page type with minor adjustments.
In /blog/code/BlogEntry.php in the BlogEntry class, add these lines to the "static $db" array:

"IsEvent" => "Boolean",
"EventName" => "Text",
"EventStartDate" => "Datetime",
"EventEndDate" => "Datetime",
"EventLocation" => "Text",
"EventMapUrl" => "Text"

2. Add the fields to the CMS interface
In the BlogEntry::getCMSFields function (before "return $fields"):

// aditional event information
		$fields->addFieldToTab("Root.Content.EventInfo", new CheckboxField("IsEvent", "This is an event"));
		$fields->addFieldToTab("Root.Content.EventInfo", new TextField("EventName", "Event Name"));
		$fields->addFieldToTab("Root.Content.EventInfo", new PopupDateTimeField("EventStartDate", "Start Date"));
		$fields->addFieldToTab("Root.Content.EventInfo", new PopupDateTimeField("EventEndDate", "End Date"));
		
		// optional: quick location chooser: change default values in /blog/javascript/eventbehaviours.js
		$quickLocations = array(
			1 => "Sample Location #1",
			2 => "Sample Location #2"
		);
		
		$fields->addFieldToTab("Root.Content.EventInfo", new DropdownField("QuickLocation", "Quick Location Chooser", $quickLocations, $value = false, $form = null, $emptyOption = "select a default location"));
		
		// not optional
		$fields->addFieldToTab("Root.Content.EventInfo", new TextAreaField("EventLocation", "Location", 3));
		$fields->addFieldToTab("Root.Content.EventInfo", new TextField("EventMapUrl", "Google Maps URL (<a href=\"http://maps.google.com\" target=\"_blank\">open Google Maps</a>)"));

3. Adding Javascript to the CMS
This step is optional, but I find it quite useful.
Add this line /blog/code/BlogEntry.php to the BlogEntry::getCMSFields function:

Requirements::javascript('blog/javascript/eventbehaviours.js');

Content of /blog/javascript/eventbehaviours.js:

// optional: adding values for default locations
Behaviour.register({
	'#Form_EditForm_QuickLocation': {
		onchange: function() {
			EventLocation = document.getElementById("Form_EditForm_EventLocation");
			EventMapUrl = document.getElementById("Form_EditForm_EventMapUrl");
			switch(this.options.selectedIndex) {
				case 1:
					EventLocation.value = "Sample Location #1";
					EventMapUrl.value = "http://maps.google.com/maps?f=q&hl=en&geocode=&q=etc...complete+link+no.1+here";
					break;
				case 2:
					EventLocation.value = "Sample Location #2";
					EventMapUrl.value = "http://maps.google.com/maps?f=q&hl=en&geocode=&q=etc...complete+link+no.2+here";
					break;
				// etc ...
				}
			},
		initialize: function() {
			this.onchange();
		}
	}
});

Behaviour.register({
	'#Form_EditForm_Title': {
		onblur: function() {
			EventName = document.getElementById("Form_EditForm_EventName");
			if(EventName.value == "" || EventName.value == "New BlogEntry"){
				EventName.value = this.value;
			}
		},
		initialize: function() {
			this.onblur();
		}
	}
});

Behaviour.register({
	'#Form_EditForm_EventStartDate_Date': {
		onblur: function() {
			EventEndDate_Date = document.getElementById("Form_EditForm_EventEndDate_Date");
			if(EventEndDate_Date.value == ""){
				EventEndDate_Date.value = this.value;
			}
		},
		initialize: function() {
			this.onblur();
		}
	}
});

Go to your site and rebuild the database http://www.mysilverstripesite.com/db/build/?flush=1 .

4. Adding event infos to the template
Now you can use the created event detail fields in the template, in the /blog/templates/Layout/BlogEntry.ss and/or /blog/templates/Includes/BlogSummary.ss (after the $Content variable). This is a simple example:

<% if IsEvent %>
	<div class="eventDetails">
		<h3>$EventName</h3>
		($EventStartDate.Ago)<br />
		$EventStartDate.Nice to $EventEndDate.Nice<br />
		$EventLocation
		<% if EventMapUrl %>
			(<a href="$EventMapUrl.XML" title="View a map">Map</a>)
		<% end_if %>
	</div>
<% end_if %>

It's then quite easy to make further additions such as a widget that displays future events in the Sidebar, parse the map URL to embed a Map of the event location with e.g. Google Maps API, etc... - but I guess this post is already too long now...

This post is just another example to see how flexible and how easy it is to extend Silverstripe. I hope it's useful for someone.

Cheers!
Anatol

Avatar
Willr

Forum Moderator, 5523 Posts

27 August 2008 at 3:07pm

Anatol - you might wish to make a page on the wiki for this. Or make a Recipe page with your post - http://doc.silverstripe.com/doku.php?idx=recipes. Hopefully makes it a bit easier for people to find!