PWaddict Posted September 6, 2020 Share Posted September 6, 2020 I would like to sort pages of specific template with a date field. The problem is that the date field might not always be filled by the editor cause he might not know yet what date to set. So, all the pages with a date should be sorted by it and those that have empty dates should sort on top. Setting the date field on the template's "Sort settings for children" sorts pages with empty dates on bottom. Link to comment Share on other sites More sharing options...
kixe Posted September 7, 2020 Share Posted September 7, 2020 I use a hook for something similar /** CUSTOM PAGE SORT * related for InputfieldPageListSelect, ProcessPageList (Page tree) * */ $wire->addHookBefore('ProcessPageList::find', function($e) { $parent = $e->arguments(1); $selectorString = $e->arguments(0); // modify $selectorString, remove, modify, add ',sort= ...' $e->arguments(0, $selectorString); }); 2 Link to comment Share on other sites More sharing options...
PWaddict Posted September 7, 2020 Author Share Posted September 7, 2020 4 hours ago, kixe said: I use a hook for something similar /** CUSTOM PAGE SORT * related for InputfieldPageListSelect, ProcessPageList (Page tree) * */ $wire->addHookBefore('ProcessPageList::find', function($e) { $parent = $e->arguments(1); $selectorString = $e->arguments(0); // modify $selectorString, remove, modify, add ',sort= ...' $e->arguments(0, $selectorString); }); Thanks for your reply but I don't understand how to sort the pages with empty date field on top... Link to comment Share on other sites More sharing options...
LostKobrakai Posted September 7, 2020 Share Posted September 7, 2020 In MySQL `NULL` is always less then any non-null value. Therefore you either need to sort at runtime, somehow make the sql query issued sort by `ISNULL(col), col` with different directions or use my paginator module for paginating though multiple different selectors: https://github.com/LostKobrakai/Paginator 2 Link to comment Share on other sites More sharing options...
PWaddict Posted September 7, 2020 Author Share Posted September 7, 2020 2 minutes ago, LostKobrakai said: In MySQL `NULL` is always less then any non-null value. Therefore you either need to sort at runtime, somehow make the sql query issued sort by `ISNULL(col), col` with different directions or use my paginator module for paginating though multiple different selectors: https://github.com/LostKobrakai/Paginator With the above hook that @kixe posted I can add multiple selectors too. I'm using 1 date field to sort pages by date but if the date is empty I want that page to be sorted on top. What's the proper selector for that??? Link to comment Share on other sites More sharing options...
PWaddict Posted September 7, 2020 Author Share Posted September 7, 2020 I've created a checkbox field named "nodate" and I checked it on a page with empty date field. Then on the above hook added the sort like this: sort=-nodate, sort=-date It seems to be working properly. Now I have to make the nodate checkbox field hidden and automatically checked on save when the editor leaves empty the date field... Link to comment Share on other sites More sharing options...
kixe Posted September 7, 2020 Share Posted September 7, 2020 I think you don't need a workaround with a hidden field if you do the hook after and change the PageArray instead of the selector. $wire->addHookAfter('ProcessPageList::find', function($e) { $pages = $e->return; if ($pages->first()->parent->id != 111111) return; // quick exit if parent doesn't match $zeroDatePages = $pages->find("date=''"); // empty date pages $result = $pages->filter('date>0,sort=-date'); // pages with date, sort descending $result->prepend($zeroDatePages); // prepend empty date pages $e->return = $result; }); 1 Link to comment Share on other sites More sharing options...
PWaddict Posted September 7, 2020 Author Share Posted September 7, 2020 12 minutes ago, kixe said: I think you don't need a workaround with a hidden field if you do the hook after and change the PageArray instead of the selector. $wire->addHookAfter('ProcessPageList::find', function($e) { $pages = $e->return; if ($pages->first()->parent->id != 111111) return; // quick exit if parent doesn't match $zeroDatePages = $pages->find("date=''"); // empty date pages $result = $pages->filter('date>0,sort=-date'); // pages with date, sort descending $result->prepend($zeroDatePages); // prepend empty date pages $e->return = $result; }); That works great on backend but on frontend I have to change the code on various pages to get the same results. I think I'm gonna do the hidden field method where I only have to change the sort. Thanks for the help. 1 Link to comment Share on other sites More sharing options...
Robin S Posted September 7, 2020 Share Posted September 7, 2020 For anyone interested in how you might do this by modifying the SQL query that's created from a PW selector, here is one way: In your template file or wherever: // A field name is supplied in a custom "empty_first" item in the $options array // The field name supplied here must also be used as a sort value in the selector string $items = $pages->find('template=news_item, sort=-date_1, limit=20', ['empty_first' => 'date_1']); In /site/ready.php: $wire->addHookAfter('PageFinder::getQuery', function(HookEvent $event) { $options = $event->arguments(1); // Return early if there is no "empty_first" item in the $options array if(!isset($options['empty_first'])) return; // Get the DatabaseQuerySelect object /** @var DatabaseQuerySelect $dqs */ $dqs = $event->return; // Prepend a custom ORDER BY $dqs->orderBy("ISNULL(_sort_{$options['empty_first']}.data) DESC", true); // Return the modified query $event->return = $dqs; }); 4 Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now