Jump to:

17452 Posts in 4473 Topics by 1971 members

Archive

SilverStripe Forums » Archive » Conditional CMS fields

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

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

Page: 1
Go to End
Author Topic: 4026 Views
  • Anatol
    Avatar
    126 Posts

    Conditional CMS fields Link to this post

    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

  • ajshort
    Avatar
    Community Member
    244 Posts

    Re: Conditional CMS fields Link to this post

    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();
          }
       },
    });

  • Anatol
    Avatar
    126 Posts

    Re: Conditional CMS fields Link to this post

    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

  • Anatol
    Avatar
    126 Posts

    Re: Conditional CMS fields Link to this post

    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

  • Willr
    Avatar
    Forum Moderator
    5508 Posts

    Re: Conditional CMS fields Link to this post

    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!

    4026 Views
Page: 1
Go to Top

Want to know more about the company that brought you SilverStripe? Then check out SilverStripe.com

Comments on this website? Please give feedback.