Jump to:

17452 Posts in 4473 Topics by 1971 members

Archive

SilverStripe Forums » Archive » ComplexTableList to show only related items

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: 1711 Views
  • Hammy
    Avatar
    Community Member
    49 Posts

    ComplexTableList to show only related items Link to this post

    I have created a relationship between 2 classes
    1. ProductPage (Page)
    2. StoreList (DataObject)

    I want to be able to list only related StoreList items for each ProductPage item in Silverstripe admin. What is the best way about doing this without listing all StoreList items in a ProductPage (eventually there will be too many StoreList items for this to be easily managed)

    Also, I would like to be able to create a StoreList item within a ProductPage and have it automatically assigned to that ProductPage.

    How do I do this? I imagine this could be a common scenario. Can this be done using ComplexTableField?

  • Sean
    Avatar
    Forum Moderator
    921 Posts

    Re: ComplexTableList to show only related items Link to this post

    You'll want to set up the relation between ProductPage and StoreList. e.g.

    ProductPage.php:

    class ProductPage extends Page {

       static $many_many = array(
          'Stores' => 'Store'
       );

       function getCMSFields() {
          $fields = parent::getCMSFields();

          $fields->addFieldToTab(
             'Root.Content.Stores',
             $this->storesTableField()
          );

          return $fields;
       }

       function storesTableField() {
          $tableField = new ManyManyComplexTableField(
             $this,
             'Stores',
             'Store',
             Store::field_list(),
             'getCMSFields'
          );

          return $tableField;
       }

    }

    class ProductPage_Controller extends Page_Controller {

    }

    Store.php:

    class Store extends DataObject {

       static $db = array(
          'Name' => 'Varchar(100)'
       );

       static $belongs_many_many = array(
          'Products' => 'ProductPage'
       );

       static function field_list() {
          return array(
             'Name' => 'Name'
          );
       }

       function getCMSFields() {
          $fields = new FieldSet(
             new TextField('Name', 'Name of store')
          );

          return $fields;
       }

    }

    This means that you've got a many-to-many relation between ProductPage <-> Store, so a Product can have many Stores, and likewise a Store has many products.

    I think this is how you'll want to set it up, let me know if I've assumed anything wrong.

    Confused? ;-)

    Cheers,
    Sean

  • Hammy
    Avatar
    Community Member
    49 Posts

    Re: ComplexTableList to show only related items Link to this post

    Thanks Sean - Kinda there but not quite

    I should have probably explained a little more about what I'm doing. I'm setting up a blog where I list products and stores that have that product. To help manage the different stores I have created the following.

    - ProductPage (Page) - that is a list of products and its details (hasMany StoreList Objects)
    - StorePage (Page) - that is a list of stores and its details (hasMany StoreList Objects)
    - StoreList (DataObject) - that lists the url to that product for that store (hasOne ProductPage and hasOne StorePage)

    Ideally what I'm kinda looking for is, when you go to a Product in the admin and add a Storelist item, it is automatically assigned to that Product (rather than going though a potential huge list of Storelist items to assign to a Product - eventually there will be hundreds of storelist items).

    Also, when you are on each product in the admin, I want to only show the StoreList items related to that Product.

    So I guess there are two things that are needed:

    1. When adding a new StoreList item, how do you make it automatically related to the Product that you are creating the StoreList item from?

    2. When viewing the list of StoreList items on a particular product, how do you filter it so that it only shows ShopList items related to that Product?

    Any suggestions? I'm a bit of a novice at this but I'm learning ;)

    This is what I have so far:

    ProductPage.php

    class ProductPage extends Page {
       
       static $db = array(
          "StartDate" => "Datetime",
          "EndDate" => "Datetime",
       );
       
       static $has_one = array(
          "ProductImage" => "Page_ResizeImages",
          "Category" => "CategoryPage",
          "Brand" => "BrandPage"
       );
       
       static $has_many = array(
          "HomeHighlight" => "HomeHighlight",
          "Stores" => "StoreList"
       );
       
       static $many_many = array(
          "Sections" => "SectionPage",
       );
       
       static $allowed_children = "none";
       
       static $default_parent = array('ProductHolder');
       
       static $icon = "themes/loaded/images/icons/product";
       
       function getCMSFields() {      
          $fields = parent::getCMSFields();
          $fields->removeFieldFromTab('Root.Content.Main', "MenuTitle");
          
          // Category Drop Down List
          $categories = DataObject::get('CategoryPage');
          $categoriesMap = $categories->toDropDownMap('ID', 'Title');
          
          // Brands Drop Down List
          $brands = DataObject::get('BrandPage');
          $brandsMap = $brands->toDropDownMap('ID', 'Title');
          
          // Sections Table Field List
          $sectionsTablefield = new ManyManyComplexTableField(
             $this,
             'Sections',
             'SectionPage',
             array('Title' => 'Sections'),
             'getCMSFields'
          );
          $sectionsTablefield->setPermissions(array());
          
          // Store Table List
          $productID = $this->ID;
          $stores = DataObject::get('StoreList');
          $storesTablefield = new ComplexTableField(
             $this,
             'Stores',
             'StoreList',
             array(
                'StoreName' => "Store Name"
             ),
             'getCMSFields_forPopup'
          );
          
          // Create Fields in CMS
          $fields->addFieldToTab('Root.Content.Main', new DropdownField('CategoryID','Category',$categoriesMap,$this,'null',true));
          $fields->addFieldToTab('Root.Content.Main', new DropdownField('BrandID',"Brand",$brandsMap,$this,'null',true));
          $fields->addFieldToTab('Root.Content.Main', $sectionsTablefield);
          $fields->addFieldToTab('Root.Content.Main', new PopupDateTimeField('StartDate','Start Date'));
          $fields->addFieldToTab('Root.Content.Main', new PopupDateTimeField('EndDate','End Date'));

          $fields->addFieldToTab('Root.Content.Stores', $storesTablefield);
          
          $fields->addFieldToTab('Root.Content.Images', new ImageField('ProductImage','Product Image'));
             
          return $fields;
       }
    }

    class ProductPage_Controller extends Page_Controller {
       
    }

    StoreList.php

    class StoreList extends DataObject {
       
       static $db = array(
          'StoreName' => 'Text',
          'ProductUrl' => 'Text',
          'Price' => 'Currency',
          'PriceRange' => "Enum('Set Price,From Price','Set Price')",
       );
       
       static $has_one = array(
          'Currency' => 'CurrencyType',
          'Store' => 'StorePage',
          'ProductPage' => 'ProductPage',
       );
       
       static $belongs_many_many = array(
       );

       function getCMSFields_forPopup() {   
          $fields = new FieldSet();
          
          // Currency Drop Down List
          $currencies = DataObject::get("CurrencyType");
          
          if(!$currencies) {
             $currenciesMap = null;
          } else {
             $currenciesMap = $currencies->toDropDownMap('ID', 'Name');
          }
          
          $currenciesDropDown = new DropdownField(
             'CurrencyID',
             'Currency',
             $currenciesMap,
             $this,
             'null',
             true
          );
          
          // Store Drop Down List
          $stores = DataObject::get("StorePage");
          if(!$stores) {
             $storesMap = null;
          } else {
             $storesMap = $stores->toDropDownMap('ID', 'Title');
          }
          
          $storeDropDown = new DropdownField(
             'StoreID',
             'Store Tracking',
             $storesMap,
             $this,
             'null',
             true
          );
          
          $fields->push(new TextField( 'StoreName', 'Store Name' ));
          $fields->push($storeDropDown);
          $fields->push(new TextField( 'ProductUrl', 'Product Url' ));
          $fields->push($currenciesDropDown);
          $fields->push(new TextField( 'Price', 'Price' ));
          return $fields;
       }
    }

  • Hammy
    Avatar
    Community Member
    49 Posts

    Re: ComplexTableList to show only related items Link to this post

    I've figured out point 2:

    In ProductPage.php i've updated the $storesTablefield variable with the following:

    ...
          $storesTablefield = new ComplexTableField(
             $this,
             'Stores',
             'StoreList',
             array(
                'Store.Title' => 'Store',
                'ProductUrl' => 'Product Url',
                'Currency.Name' => 'Currency'
             ),
             'getCMSFields_forPopup',
             'ProductID = '.$this->ID,
             '',
             ''
          );
          $storesTablefield->setParentClass('ProductPage');
    ...

    Each Product will now only list the StoreList items associated to it and also displays each StoreList items other related information from other classes (CurrencyType and StorePage) in the table field.

    (Useful info about ComplexTableField http://api.silverstripe.com/forms/fields-relational/ComplexTableField.html#sec-method-summary)

    Now just need to figure out how to automatically assign the ProductID to the StoreList item...

  • Hammy
    Avatar
    Community Member
    49 Posts

    Re: ComplexTableList to show only related items Link to this post

    Not sure if I missed something when I started on this (unless I've added something that i am unaware of) but when using complexTableField, when you add a new dataobject from a related dataobject, it is automatically assigned to the item that you created it from.

    So in my case, when you add a new Store item to a Product, it instantly creates the relationship.

    1711 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.