Jump to:

7938 Posts in 1541 Topics by 945 members

DataObjectManager Module

SilverStripe Forums » DataObjectManager Module » Dynamic dropdown field in DOM

Discuss the DataObjectManager module, and the related ImageGallery module.

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

Page: 1 2
Go to End
Author Topic: 4480 Views
  • Bright Eyes David
    Avatar
    Community Member
    26 Posts

    Dynamic dropdown field in DOM Link to this post

    I'd like to incorporate a "Type" (as in a section or a category) dropdown menu field which is dynamically populated with the entries of a DataObject called "PartType" into my DataObjectManager popup which is handling the "Part" DataObject.

    Both Part and PartType are DataObjects. Can DOM handle this?

    Many thanks.

  • tmkp
    Avatar
    Community Member
    42 Posts

    Re: Dynamic dropdown field in DOM Link to this post

    Hi David,

    not 100% sure if this is what you looking for, but I'll give it a shot anyway.

    This is a basic setup for a Discography Catalogue. Every DiscoRecord has a DiscoCategory, both are Dataobjects, and you can select the DiscoCategory in the DiscoRecord DOM Popup via dropdown.

    You could set up a new page type ("DiscoPage") with two DOMs in seperate tabs for each the records and the categories,and the "Category" dropdown in the DiscoRecord DOM popup will populate dynamically.

    <?php

    class DiscoCategory extends DataObject {

       static $db = array(
        "Title" => "Varchar(255)",
       );

       static $has_one = array (
          'Holder' => 'DiscoPage',
       );

       static $has_many = array (
          'Records' => 'DiscoRecord',
       );

       function getCMSFields() {
          $f = new FieldSet();
          $f->push( new TextField( 'Title', 'Title') );
          return $f;
       }

    }

    <?php

    class DiscoRecord extends DataObject {

       static $db = array(
        "Title" => "Varchar(255)",
       );

       static $has_one = array (
          'Holder' => 'DiscoPage',
          'Category' => 'DiscoCategory',
       );

       function getCMSFields() {
          $f = new FieldSet();

          // build dropdown menu for category selection
          $oData = (DataObject::get('DiscoCategory'));
          if ($oData) $CategoriesSource = $oData->toDropDownMap('ID','Title');
          $dropdown = new DropdownField('CategoryID', 'Category', $CategoriesSource, $this->CategoryID);
          $f->push ( $dropdown );

          // record detail fields
          $f->push( new TextField( 'Title', 'Title') );

          return $f;
       }

    }

    Note that in this example ALL DiscoCategory Dataobjects will be pulled into the dropdown, you might want to add a WHERE clause to (DataObject::get('DiscoCategory')); to make sure you're getting only the ones associated with your Holder Page.

    Hope this helps!

  • Bright Eyes David
    Avatar
    Community Member
    26 Posts

    Re: Dynamic dropdown field in DOM Link to this post

    That's great tmkp - thanks!

    I have a couple of follow on queries:

    1) I found that I had to access the DiscoPage without the DiscoRecord DOM once in order to add a DiscoCategory to avoid the following error:

    ERROR [Notice]: Undefined variable: CategoriesSource
    IN POST /admin/getitem?ID=19&ajax=1
    Line 20 in [...]/mysite/code/DiscoRecord.php

    It's not likely to be a problem, but I wondered if there was a way to cater for this event?

    2) Is it possible to show the chosen DiscoCategory for each Record on the DiscoRecord DOM tab, and to filter by it?

  • tmkp
    Avatar
    Community Member
    42 Posts

    Re: Dynamic dropdown field in DOM Link to this post

    Hi again,

    to make the DiscoRecord DOM show the selected Category for each Record put this in your DiscoPage

    ...
          /*********************************
          /* SET UP RECORDS MANAGER
          /*********************************/
          $mng_records = new DataObjectManager(
             $this, // Controller
             'Records', // Source name
             'DiscoRecord', // Source class
             array(
                   'Title' => 'Title',
                   'Category.Title' => 'Category',
             ),
             'getCMSFields_forPopup',
          );

          $f->addFieldToTab("Root.Content.Records",$mng_records);
    ...

    Back in the days when i tinkered around with this, sorting by related fields was not supported by DOM, but I think filtering might be feasible.

    As to that error, try extending the if clause to wrap up the whole dropdown constructor like so

    // build dropdown menu for category selection
    $oData = (DataObject::get('DiscoCategory'));

    if ($oData) {
       $CategoriesSource = $oData->toDropDownMap('ID','Title');
       $dropdown = new DropdownField('CategoryID', 'Category', $CategoriesSource, $this->CategoryID);
       $f->push ( $dropdown );
    } else {
       // no categories there yet, might put a literalfield to tell the user
    }

    Otherwise Silverstripe might try to create a dropdown from an empty variable if there are no categories present.

  • Bright Eyes David
    Avatar
    Community Member
    26 Posts

    Re: Dynamic dropdown field in DOM Link to this post

    I see - thanks! Working a treat now.

    The filtering doesn't seem to work on the category from within the record DOM. I've tried both "Category" and "Category.Title", but neither work.

          $mng_records->setFilter(
             'Category.Title', // The field we're filtering
             'Filter by Category', // The label for the filter field
             array(
                'asdf' => 'asdf',
                'qwer' => 'qwer'
             ) // The dropdown map of values => display text. The values will be matched against the field.
          );

    This is more of a want than a need at this stage, though.

    Thanks again!

  • tmkp
    Avatar
    Community Member
    42 Posts

    Re: Dynamic dropdown field in DOM Link to this post

    Hi David,

    glad I could help. Try this for the filter

          // Filter By Category Setup
          // only display the filter if there are categories present
          if ($oData = $this->Categories()) {
             $CategoriesSource = $oData->toDropDownMap('ID','Title');
             $mng_records->setFilter(
                'CategoryID', // The field we're filtering
                'Filter by Category', // The label for the filter field
                $CategoriesSource // The dropdown map of values
             );
          }

    It seems to work alright over here, although i did not check for pagination and PageSize support

    ----------- EDIT: -----------

    This would go into your Holder Page.

    The if clause (green bit) again will ensure that the filter only shows up if there are any categories associated with your holder page. I'm using the syntax that is documented here to get the Dataobjects from the $has_many, but you could also use the standard DataObject::get method with HolderID=$this->ID in the WHERE clause. Just looks better that way : )

    ----------- EDIT 2: -----------

    Just played around with this some more and realized that if you add a new category in the Category DOM, the Category filter dropdown in the Record DOM will not automatically update itself. Not exactly sure how to go about this.. Hitting "refresh" next to Filter by Category will make the new Categories show up though.

  • tmkp
    Avatar
    Community Member
    42 Posts

    Re: Dynamic dropdown field in DOM Link to this post

    Just trying out some new things here..

    Say for instance, if you want to have the number of associated Records show up in your Category filter dropdown, you can use a custom getter as described here.

    Just put this in your DiscoCategory

       function getDropdownSummary() {
          $String = $this->Title . " (" . $this->Records()->TotalItems() . ")";
          return $String;
       }

    And in your HolderPage Records DOM change your filter dropdown source to

          $CategoriesSource = $oData->toDropDownMap('ID','DropdownSummary');

  • tmkp
    Avatar
    Community Member
    42 Posts

    Re: Dynamic dropdown field in DOM Link to this post

    And hello once again,

    I'll post the complete code here for future reference. It's a working example with lots of room for improvement, but it's got the basic functionality covered. I'm getting no more errors when trying to create a new Record when there are no Categories, and it seems fairly stable, with filters, pagination and pagesize all working as expected.

    DiscoHolder.php

    <?php

    class DiscoHolder extends Page {

       static $has_many = array (
          'Records' => 'DiscoRecord',
          'Categories' => 'DiscoCategory',
       );

       public function getCMSFields() {
          $f = parent::getCMSFields();

          /*********************************
          /* SET UP RECORDS MANAGER
          /*********************************/
          $mng_records = new DataObjectManager(
             $this, // Controller
             'Records', // Source name
             'DiscoRecord', // Source class
             array(
                   'Title' => 'Title',
                   'Category.Title' => 'Category',
             ),
             'getCMSFields_forPopup'
          );

          // Filter By Category Setup
          // only display the filter if there are categories present
          if ($oData = $this->Categories()) {
             $CategoriesSource = $oData->toDropDownMap('ID','DropdownSummary');
             $mng_records->setFilter(
                'CategoryID', // The field we're filtering
                'Filter by Category', // The label for the filter field
                $CategoriesSource // The dropdown map of values => display text. The values will be matched against the field.
             );
          }

          $f->addFieldToTab("Root.Content.Records",$mng_records);

          /*********************************
          /* SET UP CATEGORY MANAGER
          /*********************************/
          $mng_cats = new DataObjectManager(
             $this, // Controller
             'Categories', // Source name
             'DiscoCategory', // Source class
             array(
                   'Title' => 'Title',
             ),
             'getCMSFields_forPopup'
          );

          $f->addFieldToTab("Root.Content.Categories",$mng_cats);

          // return the cms fields
          return $f;
       }

    }

    class DiscoHolder_Controller extends Page_Controller {

    }

    DiscoRecord.php

    <?php

    class DiscoRecord extends DataObject {

       static $db = array(
          "Title" => "Varchar(255)"
       );

       static $has_one = array (
          'Holder' => 'DiscoHolder',
          'Category' => 'DiscoCategory'
       );

       function getCMSFields_forPopup() {
       
          $f = new FieldSet();

          // build dropdown menu for category selection
          $myholder = $this->Holder()->ID;
          $oData = DataObject::get("DiscoCategory", "HolderID = '$myholder'");

          // but only show the dropdown if there are any categories associated with the holder page
          if ($oData) {
             $CategoriesSource = $oData->toDropDownMap('ID','Title');
             $dropdown = new DropdownField('CategoryID', 'Category', $CategoriesSource, $this->CategoryID);
             $f->push ( $dropdown );
          }
          
          // record detail fields
          $f->push( new TextField('Title','Title') );
          
          return $f;
          
       }

    }

    DiscoCategory.php

    <?php

    class DiscoCategory extends DataObject {

       static $db = array(
          "Title" => "Varchar(255)"
       );

       static $has_one = array (
          'Holder' => 'DiscoHolder'
       );
       
       static $has_many = array (
          'Records' => 'DiscoRecord'
       );
       
       function getCMSFields_forPopup() {
          $f = new FieldSet();
          $f->push( new TextField( 'Title', 'Title') );
          return $f;
       }

       function getDropdownSummary() {
          $String = $this->Title . " (" . $this->Records()->TotalItems() . ")";
          return $String;
       }

    }

    Schönes Wochenende!

    Andi

    4480 Views
Page: 1 2
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.