You should do the ordering on the database. Is the idea that if the selected item is in the rows, it always comes first?
Query Builder custom sorting pre-pagination
I have a livewire component that loads all records and then sorts the collection based on whether a query param is present. This works great as intended, where the "active" record becomes the first record listed, but I haven't been able to get pagination working when I need to sort, pre-pagination.
use App\Models\MyResults;
use Livewire\Component;
use Livewire\WithPagination;
use Illuminate\Http\Request;
class ResultSets extends Component
{
public $userColor;
public $resultSets;
public $active;
public $results;
protected $listeners = [
'updatedResults' => '$refresh'
];
protected $queryStrings = [
'active',
];
public function mount($userColor, Request $request)
{
$this->userColor = $userColor;
$this->active = $request->active;
$this->updateResultSets();
}
public function boot()
{
$this->updateResultSets();
}
public function updateResultSets()
{
$this->resultSets = MyResults::orderBy('created_at','desc')->get();
if( isset($this->active) ) {
$selected = $this->active;
$this->resultSets = $this->resultSets->sort(function ($a, $b) use ($selected) {
return ($selected != $b->id) ? -1 : 1;
});
}
}
public function render()
{
return view('livewire.my-result-sets');
}
}
The above works well, with the exception of pagination.
I have attempted to build my own pagination instance, but the results do not update when changing pages. This is my first attempt at building a custom pagination instance, so I guess I could be missing something, here.
use App\Models\MyResults;
use Livewire\Component;
use Livewire\WithPagination;
use Illuminate\Http\Request;
class ResultSets extends Component
{
use WithPagination;
public $userColor;
public $active;
public $results;
protected $listeners = [
'updatedResultSets' => '$refresh'
];
protected $queryStrings = [
'active',
];
public function mount($userColor, Request $request)
{
$this->userColor = $userColor;
$this->active = $request->active;
}
public function componentQuery()
{
$results = MyResults::orderBy('created_at','desc')->get();
if( isset($this->active) ) {
$selected[] = $this->active;
$results = $results->sort(function ($a, $b) use ($selected) {
return ($selected[0] != $b->id) ? -1 : 1;
});
}
$this->results = $results;
return $results;
}
public function buildPaginationFrom($collection)
{
$perPage = 10;
$currentPage = \Illuminate\Pagination\Paginator::resolveCurrentPage() ?? 1;
$itemsOnPage = $collection->skip(10 * ($currentPage-1))->take($perPage);
$paginatorPath = \Illuminate\Pagination\Paginator::resolveCurrentPath();
$instance = new \Illuminate\Pagination\LengthAwarePaginator(
$itemsOnPage,
$collection->count(),
$perPage,
$currentPage,
['path' => $paginatorPath]
);
return $instance;
}
public function render()
{
return view('livewire.my-result-sets', [
'resultSets' => $this->componentQuery(),
'paginator' => $this->buildPaginationFrom($this->results),
]);
}
}
What am I missing to get this working and is there a better way?
TIA.
@whoisthisstud no I simply meant that you should do the complete logic in this statement (you would probably need a raw query using CASE)
$this->resultSets = MyResults::orderBy('created_at','desc')->paginate();
Please or to participate in this conversation.