Question

I have added a widget to a Page with a class of Page. The widget php code returns a PaginatedList and it is successfully rendering in my Page.ss template using the $SidebarView tag.

How can I hijack the pagination click to have the widget rendered with a new template? I assume that testing for is_ajax on the index method and doing a $this->renderWith('myTemplate') is not going to work since I only want to render the widget with the new template, not the whole page.

Here is my current Page.php code drawing from Zauberfisch's original answer:

public function index( SS_HTTPRequest $request ) {
    $page = $this->data();

    if ( $request->isAjax() ) {
        $widgetArea = $page->Sidebar();
        $widget = $widgetArea->Widgets()->filter( 'ClassName', 'ScbWidget' );
        return $widget->renderWith( 'ScbTemplate' );
        } else {
        return array();
    }
}

and here is my widget php code that returns the paginated list to my template:

public function ScbList() {
    $list = new PaginatedList( CatalogItem::get()->filter( array( 'SchoolChoirRelease' => 1 ) ), Controller::curr()->getRequest() );
    $list->setPageLength( $this->ShowPerPage );
    return $list;
}

When the paginated list is returned to the template without ajax, everything works as expected - ?start=2 returns the list offset by 2 items. When I hijack the link and render the widget using the new template, my list is not being rendered in the new template. Here is my js:

ajaxify = function( href, callback ) {
    $.ajax( {
        url: href,
        success: function( data ) {
            callback( data );
        }
    });
};

hijackSubmit = function() {
    jqueryMap.$pagination.on( 'click', 'a', function( e ) {
        e.preventDefault();
        var href = $( this ).attr( 'href' );

        ajaxify( href, function( data ) {
          jqueryMap.$container.html( data );
        } );
    });
};
Was it helpful?

Solution

In SilverStripe any object of type ViewableData can be rendered. Page is a subclass of ViewableData, but so is Widget. A lot of objects in SilverStripe extend ViewableData.

This means you are already on the right track. I am assuming you have 2 variables:

  • $request a request object of type SS_HTTPRequest
    (if you are in a Controller, you can get it like this: $request = $this->getRequest())
  • $page a page object of type Page or subclass.
    (if you are in a Controller, you can get it like this: $page = $this->data())

now you should be able to do:

if ($request->isAjax()) {
    $widgetArea = $page->SideBar();
    $widget = $widgetArea->Widgets()->filter('ClassName', 'MyWidget')->First();
    return $widget->renderWith('MyWidgetTemplate');
}
// do something else

NOTE: if $request->isAjax() is never true, add ?ajax=1 to the URL when you call it in javascript. ?ajax=1 will let SilverStripe know that this is an ajax request.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top