Jump to:

7940 Posts in 1543 Topics by 946 members

DataObjectManager Module

SilverStripe Forums » DataObjectManager Module » New Stuff!

Discuss the DataObjectManager module, and the related ImageGallery module.

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

Page: 1 2 3
Go to End
Author Topic: 3416 Views
  • UncleCheese
    Avatar
    4085 Posts

    New Stuff! Link to this post

    Just checked in a bunch of new stuff:

    Custom DOM Actions

    A lot of people have been asking about how to create a custom action on the list view of a DOM in addition to edit, delete, and recently, duplicate. In the following example, I'll show you how to add a custom action to a Listing object that sets its status to "Approved" or "Unapproved" by clicking an an icon in the DOM, without having to edit the record in the popup.

    Listing.php

       public function customDOMActions()
       {
          $title = $this->Approved ? "Disapprove" : "Approve";
          $image = $this->Approved ? "delete.png" : "accept.png";

          return new DataObjectManagerAction(
             $title,
             "/ListingPage_Controller/approve/$this->ID",
             "refresh",
             "/mysite/images/$image"
          );
       }

       public function toggleApproved()
       {
          if($this->getField('Approved') == 1)
             $this->setField('Approved',0);
          else
             $this->setField('Approved',1);
          $this->write();
          
       }
       

    We create a function with the name "customDOMActions" in the DataObject. The name of this function is compulsory. If you have multiple custom actions, you can return them in a DataObjectSet. The arguments for a DataObjectManagerAction are as follows:

    $title : The title of the action. In this case, "approve" or "disapprove"
    $link : Link to the action. We'll handle the request on the ListingPage controller
    $behaviour : Options for the behavior of this action:

              - "refresh" : Runs the action and refreshes the DOM on success.
              - "popup" : Load the link into a popup window (like edit view)
              - "delete" : Remove the record from the DOM after executing the link

    $icon : URL to the icon for the action

    In the function toggleApprove we run a simple update that toggles the object status.

    Now we'll handle the custom action request in a custom controller.

    Listing_Controller

    class Listing_Controller extends Controller {
       static $url_handlers = array(
          'approve/$ID' => 'handleApprove'
       );

       public function handleApprove($request)
       {
          if($listing = DataObject::get_by_id("Listing",$request->param('ID'))) {
             $listing->toggleApproved();
          }
       }
    }

    That's it! You can now click the approve/disapprove icon in your list view to update the record without instantiating a popup. There are many other applications for this feature. This is just one of many possibilities.

    Many thanks to forum member Nick Jacobs for sponsoring this feature.

    New Popup Form Styling

    Updated CSS of the DOM popup to place the pagination and save button in a fixed position at the bottom of the frame, so they are always visible regardless of your scroll. Also add a transparent PNG to help ease the bottom of the viewport and bring some definition to the actions bar against the fieldset.

    Bug Fix: DOM Items Lose Sort in Popup Pagination

    Fixed this issue. You can now act on the DOM sort or pagination and the records retain their order when paginated in the popup with the prev/next buttons.

  • banal
    Avatar
    Community Member
    901 Posts

    Re: New Stuff! Link to this post

    Hi UncleCheese

    Thanks a lot for these great new features. I think the Custom DOM Actions are especially useful.

    I tested this and found the following issues:
    Your example code didn't work for me. I had to remove the slashes before the action link and the image.

    return new DataObjectManagerAction(
       $title,
       "ListingPageController/approve/$this->ID",
       'refresh',
       "site/images/$image"
    );

    There's also a potential security risk in your example code.
    When somebody uses your example, it becomes possible to alter DataObjects without being logged in to the CMS. This by simply visiting an address like this:
    http://somedomain.xx/ListingPage_Controller/approve/2

    This would approve the Listing DataObject with ID 2, and doesn't require a login!
    I'm aware that this kind of URL is probably pretty hard to figure out, but as soon as somebody posts some example code here, his site can be modified this way.

    So to anybody who wants to use this feature, secure the access to your method(s) by putting something like this in your Controller class:

    static $allowed_actions = array(
       'handleApprove' => 'CMSMain'
    );

    Access to the 'handleApprove' method will then only be granted if the current user has access to "CMSMain" (Site Content).
    If you got actions like "rss" for RSS Feeds and the like, add them to the array of allowed actions, without access constraint:

    static $allowed_actions = array(
       'rss',
       'myPublicAction',
       'handleApprove' => 'CMSMain'
    );

    This just as a notice/warning to anybody who wishes to use these features.
    And thanks to UncleCheese for providing us with these nice updates ;)
    Way to go.

  • UncleCheese
    Avatar
    4085 Posts

    Re: New Stuff! Link to this post

    Thanks, Banal. Yeah, I coded that up pretty quickly, and I wasn't thinking. Thanks very much for pointing that out. It's so easy to forget that just because a URL is usually called from the CMS doesn't mean it has to be.

    Glad you like everything. I think this will get a lot of use.

  • vancouverWill
    Avatar
    Community Member
    121 Posts

    Re: New Stuff! Link to this post

    once again, congratulations Uncle Cheese. great addition. how would I go about putting a header on to the top of the table so that can people can tell straight away that that is the approve column without having to hover over it? Thanks

    Will

  • UncleCheese
    Avatar
    4085 Posts

    Re: New Stuff! Link to this post

    Yeah, good point. It isn't really set up to do that right now. The other buttons -- edit, delete do not have a header. They rely on definitive icons to state their purpose. If you omit the icon argument, the text "Approve" will display, and that will be clearer to the user.

  • vancouverWill
    Avatar
    Community Member
    121 Posts

    Re: New Stuff! Link to this post

    How do you combine it in to a dataobjectset

    First I tried this which I guess wasn't really the point but I thought I'd give it a try

    public function customDOMActions()
    {
    $title = $this->Approved ? "Disapprove" : "Approve";
    $image = $this->Approved ? "disapprove.png" : "approve.png";
       
          $featuredTitle = $this->IsFeaturedProject ? "Disable Featured" : "Make Featured";
          $featuredImage = $this->IsFeaturedProject ? "disapprove.png" : "approve.png";

    return new DataObjectManagerAction(
    $title,
    "/ProjectPage_Controller/approve/$this->ID",
    "refresh",
    "/assets/graphics/$image"
    );
       
        return new DataObjectManagerAction(
    $featuredTitle,
    "/ProjectPage_Controller/feature/$this->ID",
    "refresh",
    "/assets/graphics/$featuredImage"
    );
    }

    then I tried this

    public function customDOMActions()
    {
    $title = $this->Approved ? "Disapprove" : "Approve";
    $image = $this->Approved ? "disapprove.png" : "approve.png";
       
          $featuredTitle = $this->IsFeaturedProject ? "Disable Featured" : "Make Featured";
          $featuredImage = $this->IsFeaturedProject ? "disapprove.png" : "approve.png";
       
       $collection = new DataObjectSet;
       
       $collection = ((
    new DataObjectManagerAction(
    $title,
    "/ProjectPage_Controller/approve/$this->ID",
    "refresh",
    "/assets/graphics/$image"
    )),(
       
        new DataObjectManagerAction(
    $featuredTitle,
    "/ProjectPage_Controller/feature/$this->ID",
    "refresh",
    "/assets/graphics/$featuredImage"
    )));
       
        return $collection;
    }

    They both work seperately so I was hoping it is an easy fix to combine them together. I had a look on the dataobjectset page but couldn't see how to add them together. Thanks again

  • vancouverWill
    Avatar
    Community Member
    121 Posts

    Re: New Stuff! Link to this post

    Had a look a bit further and I found the easy fix

    public function customDOMActions()
    {
    $title = $this->Approved ? "Disapprove" : "Approve";
    $image = $this->Approved ? "disapprove.png" : "approve.png";
       
          $featuredTitle = $this->IsFeaturedProject ? "Disable Featured" : "Make Featured";
          $featuredImage = $this->IsFeaturedProject ? "disapprove.png" : "approve.png";
       
       $collection = new DataObjectSet();
       
       $collection->push(
    new DataObjectManagerAction(
    $title,
    "/ProjectPage_Controller/approve/$this->ID",
    "refresh",
    "/assets/graphics/$image"
    ));
       
       $collection->push(
          new DataObjectManagerAction(
    $featuredTitle,
    "/ProjectPage_Controller/feature/$this->ID",
    "refresh",
    "/assets/graphics/$featuredImage"
    ));
       
        return $collection;
    }

    worked just as I hope. Thanks UncleCheese

    edit: I guess the key lines I was looking for were

    $collection = new DataObjectSet();

    $collection->push(


    if that helps anyone else hope that is useful.

  • UncleCheese
    Avatar
    4085 Posts

    Re: New Stuff! Link to this post

    Yup. You got it. You can also do:

    new DataObjectSet(
    new DataObjectManagerAction(),
    new DataObjectManagerAction()
    );

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