SilverStripe - Create pagination based on dropdown selection

后端 未结 1 1473
野的像风
野的像风 2021-01-20 02:14

I am working on building out some pagination for a page on a SilverStripe site that is meant to show all articles at first by default, but the user can select which articles

1条回答
  •  鱼传尺愫
    2021-01-20 02:55

    There's definitely room for improvement when you return JSON to build HTML markup from JSON…

    I also think it's good practice to write your application logic in a way that works without JS, then add the JS to progressively enhance your application. That way you don't lock out every non-JS device/reader/user.

    So here's what I'd do (prepare for extensive answer):

    Enable filtering by year

    First of all, you want to be able to filter your records by year. I think your approach of enabling filtering via URL is fine, so that's what we're going to do:

    1. Get paginated list, optionally filtered by year

    In your controller, add/modify the following method:

    public function PaginatedReleases($year = null)
    {
        $list = NewsReleaseArticlePage::get()->sort('ArticleDate', 'DESC');
        if ($year) {
            $list = $list->where(array('YEAR("ArticleDate") = ?' => $year));
        }
        return PaginatedList::create($list, $this->getRequest());
    }
    

    This will allow you to get all entries, or only the ones from a certain year by passing in the $year parameter.

    2. Add a year action to your controller

    public static $allowed_actions = array(
        'year' => true
    );
    
    public function year()
    {
        $year = $this->request->param('ID');
        $data = array(
            'Year' => $year,
            'PaginatedReleases' => $this->PaginatedReleases($year)
        );
        return $data;
    }
    

    After running dev/build, you should already be able to filter your entries by year by changing the URL (eg. mypage/year/2016 or mypage/year/2015 etc.)

    Use a form with a dropdown to filter

    Add the following to your controller to create a form to filter your entries:

    public function YearFilterForm()
    {
        // get an array of all distinct years
        $list = SQLSelect::create()
            ->addFrom('NewsReleaseArticlePage')
            ->selectField('YEAR("ArticleDate")', 'Year')
            ->setOrderBy('Year', 'DESC')
            ->addGroupBy('"Year"')->execute()->column('Year');
    
        // create an associative array with years as keys & values
        $values = array_combine($list, $list);
    
        // our fields just contain the dropdown, which uses the year values
        $fields = FieldList::create(array(
            DropdownField::create(
                'Year',
                'Year',
                $values,
                $this->getRequest()->param('ID')
            )->setHasEmptyDefault(true)->setEmptyString('(all)')
        ));
    
        $actions = FieldList::create(array(
            FormAction::create('doFilter', 'Submit')
        ));
    
        return Form::create($this, 'YearFilterForm', $fields, $actions);
    }
    

    Implement the doFilter function. It simply redirects to the proper URL, depending what year was selected:

    public function doFilter($data, $form)
    {
        if(empty($data['Year'])){
            return $this->redirect($this->Link());
        } else {
            return $this->redirect($this->Link('year/' . $data['Year']));
        }
    }
    

    Don't forget to add the Form name to the allowed_actions:

    public static $allowed_actions = array(
        'YearFilterForm' => true, // <- this should be added!
        'year' => true
    );
    

    Now delete your

    提交评论

提交回复
热议问题