Grouping by months
Closed this issue · 8 comments
Question: is it possible to group list by months?
Details: I have a list of future events that I would like to be grouped by months so it would look like this:
January
- Event 1 title
- Event 2 title
- Event 3 title
February
- Event 4 title
- Event 5 title
August
- Event 6 title
- Event 7 title
Is it possible with DocLister?
Resources are using template variables: event_date_start, event_date_end
Look at DLReflect or DLReflectFilter
Thanks, but could you please give here an example of a call of DLReflect and DLReflectFilter to get the result I need?
Give more information about your task
I have a list of future events that I would like to be grouped by months.
Right now it is just a simple list (DocLister) with future events outputed like this:
Event 1 (March 15)
Event 2 (March 21)
Event 3 (June 18)
I need it like this:
March:
Event 1 (March 15)
Event 2 (March 21)
June:
Event 3 (June 18)
More information:
I use two template variables
event_date_start
event_date_end
.
To filter out past events I use this:
$params['filters'] = 'AND(tvdate:event_date_end:>:'.$current_date.')';
You should't use only a month for filtering.
- December 2017
- January 2018
- December 2018
DLReflect will build a month + year list.
DLReflectFilter will filter documents by month + year.
To build one list, you need a snippet that combines the functional DLReflect + DLReflectFilter
Wait for the news. I will do it specifically for you :-)
Thanks @AgelxNash, really appreciate it.
<?php
$months = $modx->runSnippet('DocLister', array(
'tvList' => 'event_date_start',
'orderBy' => 'event_date_start ASC',
'saveDLObject' => 'DLAPI',
'api' => 'id',
'tvSortType' => 'TVDATETIME',
'addWhereList' => "STR_TO_DATE(`dltv_event_date_start_1`.`value`,'%d-%m-%Y %H:%i:%s') >= now()",
'selectFields' => "DATE_FORMAT(STR_TO_DATE(`dltv_event_date_start_1`.`value`,'%d-%m-%Y %H:%i:%s'), '%m-%Y') as `id`"
));
$months = json_decode($months, true);
if (is_null($months)) $months = array();
$months = new DLCollection($modx, $months);
/**
* Filtering and sorting with PHP
* Not necessary!!!
*/
// <FilterAndSort>
$months->filter(function ($el) {
return !empty($el['id']);
})->filter(function($el) {
$aDate = DateTime::createFromFormat('m-Y', $el['id']);
return $aDate->getTimestamp() >= time();
})->sort(function ($a, $b) use ($dateFormat) {
$aDate = DateTime::createFromFormat('m-Y', $a['id']);
$bDate = DateTime::createFromFormat('m-Y', $b['id']);
return $aDate->getTimestamp() - $bDate->getTimestamp();
})->reindex()->unique();
// </FilterAndSort>
$DLAPI = $modx->getPlaceholder('DLAPI');
$DLAPI->loadLang('months');
$out = '';
foreach($months as $item){
list($vMonth, $vYear) = explode('-', $item['id'], 2);
$filter = "STR_TO_DATE(`dltv_event_date_start_1`.`value`,'%d-%m-%Y %H:%i:%s') >= NOW() AND
DATE_FORMAT(STR_TO_DATE(`dltv_event_date_start_1`.`value`,'%d-%m-%Y %H:%i:%s'), '%m-%Y') ='".$item['id']."'";
$docs = $modx->runSnippet('DocLister', array(
'tvList' => 'event_date_start',
'orderBy' => 'event_date_start ASC',
'tvSortType' => 'TVDATETIME',
'addWhereList' => $filter,
'tpl' => '@CODE: <li>[+title+]</li>',
'ownerTPL' => '@CODE: <ul>[+dl.wrap+]</ul>'
));
$data = array(
'monthNum' => $vMonth,
'monthName' => $DLAPI->getMsg('months.' . (int)$vMonth),
'year' => $vYear,
'docs' => $docs
);
$out .= $DLAPI->parseChunk('@CODE: <li>[+monthName+] ([+monthNum+]) [+year+] [+docs+]</li>', $data);
}
if(!empty($out)){
$out = $DLAPI->parseChunk('@CODE: <ul>[+out+]</ul>', compact('out'));
}else{
$out = 'N\A';
}
return $out;
This example can form many nested calls to the DocLister. You can optimize using only 2 calls DocLister calls and DLCollection filtering.
That's perfect! Exactly what I needed and works great. Thank you for your effort! I owe you a 🍺