Closed franzdumfart closed 6 years ago
I’m on mobile now but can you try overriding indexQuery method on the resource and put it there?
@crnkovic is correct @franzdumfart
This can be accomplished by overloading the indexQuery
method.
Unfortunately the solution is slightly more fugly than probably desired, because the order by id beats the request to the query. But this works fine.
const DEFAULT_INDEX_ORDER = 'last_name';
public static function indexQuery(NovaRequest $request, $query)
{
$query->when(empty($request->get('orderBy')), function(Builder $q) {
$q->getQuery()->orders = [];
return $q->orderBy(static::DEFAULT_INDEX_ORDER);
});
}
I should note, that the UI state and url state does not know sorting has been changed. So if you are sorting by a column that is visible by default, the UI will not reflect that.
See suggestion from @jasonlav, this is a bit more desirable.
Thanks so much, this helps! Will extend all my Nova resources from a Base class and add a helper method there, so I can use it on every Resource with just setting one property. Hopefully this will be implemented someday in Nova itself. Need this very often.
Slightly, updated code to make it one line per Resource.
In App/Nova/Resource.php
:
public static $defaultSort = null; // Update to your default column
/**
* Build an "index" query for the given resource.
*
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
* @param \Illuminate\Database\Eloquent\Builder $query
* @return \Illuminate\Database\Eloquent\Builder
*/
public static function indexQuery(NovaRequest $request, $query)
{
if (static::$defaultSort && empty($request->get('orderBy'))) {
$query->getQuery()->orders = [];
return $query->orderBy(static::$defaultSort);
}
return $query;
}
In any resource where you want to change the sort:
public static $defaultSort = 'name';
Thanks @loren138, works perfect! We also should add another static variable like public static $defaultSortDirection = null;
to define the direction. I think we can close this one.
I added protected static $sort = ['id' => 'desc'];
and then returned $query->orderBy(key(static::$sort), reset(static::$sort));
:)
I hate that PHP doesn't have tuples, god damn.
Nice solution, though. :)
@franzdumfart Probably shouldn't close it until it is a feature request or a pull request.
I've ended with this code in App\Nova\Resource
/**
* Default ordering for index query.
*
* @var array
*/
public static $indexDefaultOrder = [
'id' => 'desc'
];
/**
* Build an "index" query for the given resource.
*
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
* @param \Illuminate\Database\Eloquent\Builder $query
* @return \Illuminate\Database\Eloquent\Builder
*/
public static function indexQuery(NovaRequest $request, $query)
{
if (empty($request->get('orderBy'))) {
$query->getQuery()->orders = [];
return $query->orderBy(key(static::$indexDefaultOrder), reset(static::$indexDefaultOrder));
}
return $query;
}
Thanks for all the suggestions! 🙌
How 'bout sorting on a relation field...?
For example, activities belong to an event and an event has a date. If you view activities, you may want to sort on their event dates.
This repository is for tracking bugs. Feature requests may be emailed to Nova customer support.
@taylorotwell Is the customer support email listed somewhere on the Nova website? The only email I've been able to find so far is your email from the composer.json
file.
@taylorotwell Is it possible to open a nova-feature-requests repository, so we can all submit to that?
The applyOrderings
method from Laravel\Nova\PerformsQueries
can be overridden on a per-model basis to set default ordering.
It's seems that this approach does not works on relationship models.
So I put a orderBy()
on my Model.
public function comments()
{
return $this->belongsToMany('App\Posts')
->withPivot('order')
->orderBy('order');
}
I'm trying to resolve this myself at the moment, could you provide a more detailed example please @jasonlav? Attempting to set the default sort order for a HasMany-related resource.
e.g. Town resource has many Roads, which appear as a relationship when viewing a Town. Attempting to simply sort the Roads panel by name ascending, without success. Perhaps my brain is just broken at the moment :)
The PerformsQueries
trait -- implemented by Nova's Resource
class -- has an applyOrderings
method that can be overwritten on the Nova Resource for custom sorting.
/**
* Apply any applicable orderings to the query.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param array $orderings
* @return \Illuminate\Database\Eloquent\Builder
*/
protected static function applyOrderings($query, array $orderings)
{
if (empty($orderings)) {
// To maintain user-initiated column sorting, I would recommend placing your custom sorting here.
return empty($query->orders)
? $query->latest($query->getModel()->getQualifiedKeyName())
: $query;
}
foreach ($orderings as $column => $direction) {
$query->orderBy($column, $direction);
}
return $query;
}
public static $indexDefaultOrder = [
'id' => 'desc'
];
public static function indexQuery(NovaRequest $request, $query)
{
if (empty($request->get('orderBy'))) {
$query->getQuery()->orders = [];
return $query->orderBy(key(static::$indexDefaultOrder), reset(static::$indexDefaultOrder));
}
return $query;
}
This code is working. But i have several questions. I am using this query without order
$companyID= Company::where('user_id', auth()->user()->id)->first()->id;
return $query->where('company_id', $companyID)->first();
This is showing users own data. Other users informations are not displaying. When i use with order query its showing all data. All user can display all datas. How can i add my own query with order?
I made this. But when sort some column. All datas showing up again...
public static $indexDefaultOrder = [
'id' => 'desc'
];
public static function indexQuery(NovaRequest $request, $query)
{
$companyID= Company::where('user_id', auth()->user()->id)->first()->id;
if (empty($request->get('orderBy'))) {
$query->where('company_id', $companyID)->getQuery()->orders = [];
return $query->where('company_id', $companyID)->orderBy(key(static::$indexDefaultOrder), reset(static::$indexDefaultOrder));
}
return $query;
}
How can i solve this. How can i use order and display limit (each user) together?
The
PerformsQueries
trait -- implemented by Nova'sResource
class -- has anapplyOrderings
method that can be overwritten on the Nova Resource for custom sorting./** * Apply any applicable orderings to the query. * * @param \Illuminate\Database\Eloquent\Builder $query * @param array $orderings * @return \Illuminate\Database\Eloquent\Builder */ protected static function applyOrderings($query, array $orderings) { if (empty($orderings)) { // To maintain user-initiated column sorting, I would recommend placing your custom sorting here. return empty($query->orders) ? $query->latest($query->getModel()->getQualifiedKeyName()) : $query; } foreach ($orderings as $column => $direction) { $query->orderBy($column, $direction); } return $query; }
Using this approach I ended up with a simple overwrite in my base Resource
file
protected static function applyOrderings($query, array $orderings)
{
if (empty($orderings) && property_exists(static::class, 'orderBy')) {
$orderings = static::$orderBy;
}
return parent::applyOrderings($query, $orderings);
}
Now in any Resource I can simple add
public static $orderBy = ['name' => 'asc'];
Works like a charm
I used sorting by overriding the indexQuery method. But when I try to apply filters they do not work. What could be the reason?
I have my resource like : ` ID::make()->sortable(),
Text::make('Content', 'content', function() {
return '<a href="' . $this->getContentLink() . '" target="_blank">'.$this->content->title->title.'</a>';
})->asHtml()->hideWhenUpdating()->sortable(),
Text::make('Seller', function(){
return $this->content->organization->company_name;
})->hideWhenUpdating()->sortable(),
Text::make('Buyer', function() {
if(empty($this->parent_offer_id) || $this->created_by_buyer == 1) {
return $this->user->organization->company_name;
}else {
$parentOffer = AppOffer::find($this->parent_offer_id);
return $parentOffer->user->organization->company_name;
}
})->hideWhenUpdating()->sortable(),`
The sorting doesn't work on the seller and buyer. What is the way to implement it ?
For anyone else still coming back to this issue, Nova v3.19.1 introduced changes that (at least for me) broke @rasmuscnielsen's awesome workaround. Nova now explicitly orders all index queries by a resource model's primary key by default, so to get the snippet above working again, I had to remove the orderBy
clauses manually:
protected static function applyOrderings($query, array $orderings)
{
if (empty($orderings) && property_exists(static::class, 'orderBy')) {
+ $query->reorder();
$orderings = static::$orderBy;
}
return parent::applyOrderings($query, $orderings);
}
If you sort a field and cycle through until you're not sorting any more (click the field name three times), you can end up with a null
entry in the $orderings
array, e.g. ['quantity' => null]
.
To make sure you're still applying your custom default sort, filter the orderings array:
protected static function applyOrderings($query, array $orderings) { - if (empty($orderings) && property_exists(static::class, 'orderBy')) { + if (empty(array_filter($orderings)) && property_exists(static::class, 'orderBy')) { $query->reorder(); $orderings = static::$orderBy; } return parent::applyOrderings($query, $orderings); }
@rdarcy1 That's fixed by now (3.29 anyway).
It now looks like this (I have changed latest
to oldest
because that's the order I wanted).
protected static function applyOrderings($query, array $orderings)
{
$orderings = array_filter($orderings);
if (empty($orderings)) {
return empty($query->getQuery()->orders) && ! static::usesScout()
? $query->oldest($query->getModel()->getQualifiedKeyName())
: $query;
}
foreach ($orderings as $column => $direction) {
$query->orderBy($column, $direction);
}
return $query;
}
Is this still the best way with Nova 4?
^ +1, Nova 4 still the best way? Seems strange it wasn't implemented if so
Still the same solution, nothing implemented in Nova 4.
Found nothing in the docs, so here is my question:
How can I set the default ordering of a Resources items on list view? At the moment it looks like it is
orderBy('id', 'desc')
. Setting the first visible and sortable field would be a great indicator for the planned behavior. Or is possible the set it via a property or method?