Skip to content

Scope Types ​

The Filter widget is a bar of scopes above a list. Each scope narrows the list: a checkbox, a switch, a dropdown, or a label that opens a popover with a small form. bindToListWidget() applies the active scopes to the list query and refreshes the list when one changes. Each scope remembers its value for the session, and the menu at the start of the bar clears them all. Adding a filter to a page is covered in Building a List Page.

The filters on this page ​

Each example binds a filter, with the scopes from its own YAML file, to a list of the seeded posts. The lists share one columns file.

php
<?php

namespace App\Controllers\Reference\FiltersController;

use App\Models\Post;
use Larajax\Ui\Widgets\Filter;
use Larajax\Ui\Widgets\Lists;

/**
 * ScopesExamples builds the filters on the Scope Types page, each bound to its own list of posts.
 */
trait ScopesExamples
{
    /**
     * makeScopeExamples builds a filter for each scope type example, with the scopes from its YAML file, bound to a list of posts.
     *
     * @return array<string, array{filter: Filter, list: Lists}>
     */
    protected function makeScopeExamples(): array
    {
        $examples = [];

        foreach (['checkbox', 'switch', 'dropdown', 'group', 'date', 'text', 'number'] as $name) {
            $list = Lists::make(
                alias: $name.'List',
                model: new Post,
                columns: '~/resources/ui/reference/filters/posts.yaml',
                recordsPerPage: 5,
                noRecordsMessage: 'No posts match the filter.',
                customPageName: false,
            );

            $filter = Filter::make(
                alias: $name.'Filter',
                model: new Post,
                scopes: "~/resources/ui/reference/filters/scopes/{$name}.yaml",
            );

            $filter->bindToListWidget($list);

            $examples[$name] = ['filter' => $filter, 'list' => $list];
        }

        return $examples;
    }
}
yaml
columns:
    title:
        label: Title
        searchable: true

    category:
        label: Category
        relation: category
        select: name

    tags:
        label: Tags
        type: partial
        path: ~/resources/views/reference/lists/columns/_column_tags.php
        relationWith: tags
        sortable: false

    status:
        label: Status
        type: selectable

    published:
        label: Live
        type: switch

    views:
        label: Views
        type: number

    comments_count:
        label: Comments
        type: number
        relation: comments
        relationCount: true

    published_at:
        label: Published
        type: date
        format: j M Y

    review_on:
        label: Review
        type: date
        format: j M Y

Checkbox ​

checkbox is on or off. Off, it applies nothing. On, it keeps the records whose column of the same name is true, like published, or the records that match the SQL in conditions, like the posts with comments here.

yaml
scopes:
    published:
        label: Published
        type: checkbox

    commented:
        label: Has comments
        type: checkbox
        conditions: exists (select 1 from comments where comments.post_id = posts.id)

Switch ​

switch has three states. Click it once for the first of its two conditions, again for the second, and again to turn it off. Without conditions, the two states compare the column of the same name with false and then with true.

yaml
scopes:
    published:
        label: Published
        type: switch
        conditions:
            - published = false
            - published = true

dropdown picks one value for the column of the same name. Its options come from options in the YAML, or from optionsMethod, given here as a static method, Class::method, whose options carry icons. An option is written as value: label, or as value: [label, icon] or value: [label, color] like the options of a dropdown field. emptyOption is the option that applies no filter.

A static options method is called with the filter's model and the scope, and a plain method name is called on the filter's model with the scope.

yaml
scopes:
    status:
        label: Status
        type: dropdown
        emptyOption: Any status
        optionsMethod: App\Models\Post::listStatusOptions
php
/**
 * listStatusOptions returns the workflow statuses as a label and icon pair, shared by the form, list and filter.
 *
 * @return array<string, array{0: string, 1: string}>
 */
public static function listStatusOptions(): array
{
    return [
        'draft' => ['Draft', 'ph ph-pencil-simple'],
        'review' => ['In Review', 'ph ph-eye'],
        'approved' => ['Approved', 'ph ph-seal-check'],
        'archived' => ['Archived', 'ph ph-archive'],
    ];
}

Group ​

group opens a popover with a searchable list of options, to pick several, and the bar shows how many are picked. When the scope is named after a relation of the model, like category, the options are the related records, labelled by their nameFrom attribute, and the filter keeps the records related to any picked one. The popover lists the first 200 related records, and its search box looks up the rest.

With options or optionsMethod in place of a relation, the filter keeps the records whose column holds any picked value, or, for a column the model stores as JSON, contains one.

yaml
scopes:
    category:
        label: Category
        type: group
        nameFrom: name

    status:
        label: Status
        type: group
        options:
            draft: Draft
            review: In Review
            approved: Approved
            archived: Archived

Date ​

date compares the column with a date picked from a calendar: the popover offers is equal to, not equal to, between, before and after. daterange offers only between, and leaving one end of the range empty turns it into before or after. Equal to matches any time on the picked day, which is read in the viewer's timezone.

yaml
scopes:
    published_at:
        label: Published
        type: date

    review_on:
        label: Review Date
        type: daterange

Text ​

text matches the column against typed text, either as the whole value (is equal to) or as a part of it (contains).

yaml
scopes:
    title:
        label: Title
        type: text

Number ​

number compares the column with a number: equal to, greater than, less than, or between two numbers, where greater, less and between include the numbers given. numberrange offers only between, and leaving one end empty turns it into greater or less.

yaml
scopes:
    views:
        label: Views
        type: number

    id:
        label: ID
        type: numberrange

Scope properties ​

Every scope takes these properties, where they apply.

PropertyDescription
labelthe scope's name in the bar.
shortLabela shorter name for the bar, in place of label.
typethe scope type. Default: group.
valueFromthe column, or relation for a group, that the scope filters. Default: the scope name.
conditionsraw SQL in place of the default query. See conditions.
modelScopea model scope, or a static Class::method, in place of the default query, receiving the query and the scope with its value. See model scopes.
defaultthe value the scope starts with, and returns to when the filter is cleared. See default values.
optionsthe options of a dropdown or a group.
optionsMethoda model method, or a static Class::method, that returns the options.
emptyOptionthe label of an extra option: on a dropdown it applies no filter, and on a group it matches the records with no value.
nameFromthe attribute that labels a group's options from a relation. Default: name.
modelClassthe model that supplies a group's options and answers its options method, in place of the relation named by the scope.
dependsOna scope name, or an array of them. When one of them changes, this scope is cleared and rendered again.
permissionsgate abilities the visitor needs to see the scope, as a string or an array where any one is enough, checked with Laravel's Gate.
contextthe filter context, or an array of them, that shows the scope. A scope named name@context does the same.
cssClassa class added to the scope.
ordera number for the scope's position. Default: 100, 200 and so on, in the order of the definitions.
afterplaces the scope after the named scope.
beforeplaces the scope before the named scope.

Scope types ​

TypeShowsOptions
checkboxa checkbox, on or off.conditions, modelScope
switcha checkbox with three states: off, the first condition and the second.conditions, modelScope
dropdowna select of options, one picked.options, optionsMethod, emptyOption, conditions, modelScope
groupa popover with a searchable list, several picked.options, optionsMethod, nameFrom, modelClass, optionsScope, emptyOption, matchMode, conditions, modelScope
datea popover comparing with a picked date.conditions, minDate, maxDate, yearRange, firstDay, showWeekNumber, useTimezone, modelScope
daterangea date scope offering only between.as date
texta popover matching typed text.conditions, modelScope
numbera popover comparing with a number.conditions, modelScope
numberrangea number scope offering only between.as number

Type options ​

OptionDescription
conditionscheckbox: SQL applied while it is on. switch: a list of two SQL statements, one for each state. dropdown: SQL with :value for the picked option. group: SQL with :value for the picked values, quoted and separated by commas, as in status in (:value). date, text and number: the choices offered, keyed by name, each true for the default query or SQL of its own, as listed under conditions.
optionsScopegroup: a scope of the options model that narrows the options.
matchModegroup: toggle lets the visitor choose between including and excluding the picked options, and include or exclude fixes the mode. Default: include.
minDatedate: the first date that can be picked. Default: 1970-01-01.
maxDatedate: the last date that can be picked. Default: 2199-12-31.
yearRangedate: how many years either side the calendar's year view offers. Default: 10.
firstDaydate: the first day of the week, from 0 for Sunday. Default: the locale's.
showWeekNumberdate: numbers the weeks in the calendar. Default: false.
useTimezonedate: reads the picked days in the viewer's timezone. false compares them with the stored dates as they are. Default: true.

Filter widget ​

Filter::make() takes these options as named arguments.

OptionDescription
modelthe model the scopes filter, which also supplies relation options and options methods.
scopesthe scope definitions, as a YAML file path or an array.
contextthe filter's context, which shows only the scopes for that context.
aliasthe widget's name, unique on the page.

bindToListWidget($list) applies the active scopes to the list query, refreshes the list when a scope changes, and shares the list's page parameter, so the list goes back to its first page.