Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default ordering resource #156

Closed
franzdumfart opened this issue Aug 24, 2018 · 20 comments

Comments

@franzdumfart
Copy link

commented Aug 24, 2018

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?

@crnkovic

This comment has been minimized.

Copy link

commented Aug 24, 2018

I’m on mobile now but can you try overriding indexQuery method on the resource and put it there?

@danrichards

This comment has been minimized.

Copy link

commented Aug 24, 2018

@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.

@franzdumfart

This comment has been minimized.

Copy link
Author

commented Aug 25, 2018

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.

@loren138

This comment has been minimized.

Copy link

commented Aug 25, 2018

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';
@franzdumfart

This comment has been minimized.

Copy link
Author

commented Aug 25, 2018

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.

@crnkovic

This comment has been minimized.

Copy link

commented Aug 25, 2018

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. :)

@loren138

This comment has been minimized.

Copy link

commented Aug 25, 2018

@franzdumfart Probably shouldn't close it until it is a feature request or a pull request.

@franzdumfart

This comment has been minimized.

Copy link
Author

commented Aug 25, 2018

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! 🙌

@telkins

This comment has been minimized.

Copy link

commented Aug 26, 2018

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.

@taylorotwell

This comment has been minimized.

Copy link
Member

commented Sep 6, 2018

This repository is for tracking bugs. Feature requests may be emailed to Nova customer support.

@loren138

This comment has been minimized.

Copy link

commented Sep 7, 2018

@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.

@phoenixg

This comment has been minimized.

Copy link

commented Sep 21, 2018

@taylorotwell Is it possible to open a nova-feature-requests repository, so we can all submit to that?

@jasonlav

This comment has been minimized.

Copy link

commented Sep 25, 2018

The applyOrderings method from Laravel\Nova\PerformsQueries can be overridden on a per-model basis to set default ordering.

@carloshc

This comment has been minimized.

Copy link

commented Dec 4, 2018

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');
    }
@shane-smith

This comment has been minimized.

Copy link

commented Dec 4, 2018

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 :)

@jasonlav

This comment has been minimized.

Copy link

commented Dec 7, 2018

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;
    }
@aozen

This comment has been minimized.

Copy link

commented Jan 11, 2019

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?

@rasmuscnielsen

This comment has been minimized.

Copy link

commented Jan 23, 2019

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;
    }

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

@SHAH0001

This comment has been minimized.

Copy link

commented Apr 30, 2019

I used sorting by overriding the indexQuery method. But when I try to apply filters they do not work. What could be the reason?

@sonalmahajan01

This comment has been minimized.

Copy link

commented May 8, 2019

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 ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
You can’t perform that action at this time.