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.

Archive /

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

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

Conditional CMS fields


Reply


5 Posts   4240 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, 5513 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!