Skip to content

SmartSelect

Joe edited this page Mar 18, 2023 · 3 revisions

A Select2 style Filter built in AlpineJS. This takes a list of potential options, and allows the end-user to filter them on-the-fly, and select appropriate values.

Usage

Include the class after your namespace declaration

use LowerRockLabs\LaravelLivewireTablesAdvancedFilters\SmartSelectFilter;

To use this, you should pass the filter an array of options with values for the following keys, using the map function to return a relevant value for name. * id * name

This should take the format of: (# ⇒ { id: val, name: val })

In the filters() function in your data table component:

  SmartSelectFilter::make('Parent')
  ->options(
      Tag::select('id', 'name', 'created_at')
          ->orderBy('name')
          ->get()
          ->map(function ($tag) {
              $tagValue['id'] = $tag->id;
              $tagValue['name'] = $tag->name;
              $tagValue['htmlName'] = "<strong>" . $tag->name . "</strong>"
              return $tagValue;
          })->keyBy('id')->toArray()
      )
  ->filter(function (Builder $builder, array $values) {
      $builder->whereHas('tags', fn ($query) => $query->whereIn('tags.id', $values));
  }),

You can also pass an "htmlName" value within the array, this requires you to pass an HTML string to be displayed, to do so, you should set

->config(['displayHtmlName' => true])

To use the standard approach for the PopOver for Currently Selected Items, you should add a public array to your Data Component for storing the compiled selected items. This offers the best end-user experience.

If you would prefer to utilise an on-the-fly Alpine lookup for the name, then you should set popoverMethod in the configuration to lookup

Configuration options

The below can either be set in the configuration file, or specified per-filter by passing an array into the config() method of the filter. You can set as many or as few configuration options as you like, the remainder will be set to the default from the configuration file.

'smartSelect' => [
    'popoverMethod' => 'standard',  // Should be set to either standard or lookup
    'displayIdEnabled' => 'false', // Whether to display the ID in brackets or not
    'iconStyling' => [
        'add' => [
            'classes' => '',        // Base classes for the "add" icon
            'defaults' => true,     // Determines whether to merge (true) or replace (false) the default class (inline-block)
            'svgEnabled' => false,  // Enable or Disable the use of the default SVG icon
            'svgFill' => '#000000', // Fill for the SVG Icon
            'svgSize' => '1.5em',   // Size for the SVG Icon
        ],
        'delete' => [
            'classes' => '',        // Base classes for the "delete" icon
            'defaults' => true,     // Determines whether to merge (true) or replace (false) the default class (inline-block)
            'svgEnabled' => true,   // Enable or Disable the use of the default SVG icon
            'svgFill' => '#000000', // Fill for the SVG Icon
            'svgSize' => '1.5em',   // Size for the SVG Icon
        ],
    ],
    'listStyling' => [
        'classes' => '',            // Classes for the list items
        'defaults' => true,         // Determines whether to merge (true) or replace (false) the default classes
    ],
    'closeAfterAdd' => true,        // Close the smartSelect after adding an item
    'closeAfterRemove' => true,     // Close the smartSelect after removing an item
],

Dependencies

This uses AlpineJS. There are no other dependencies.

Examples

In this example we are displaying a drop-down of countries, with a flag icon next to each one. This will produce something like this:

The flagIcons package is used for this, in combination with a database table containing a unique ID, the name of the country, and the unique country code. There is an assumption that there is a country_id field in the table you’re working with.

First set a public array to store your options to avoid the need to pull them from the database each time.

  public array $arrayOfCountries = [];

Next populate the array from your Configure() method.

      if (empty($this->arrayOfCountries)) {
          $this->arrayOfCountries = Country::select('id', 'name', 'code')
              ->orderBy('name')
              ->get()
              ->map(function ($country) {
                  $countryValue['id'] = $country->id;
                  $countryValue['name'] = $country->name;
                  $countryValue['htmlName'] = "<span><span class='fi fi-" . strtolower($country->code) . "'></span>" . $country->name . "</span>";

                  return $countryValue;
              })
              ->keyBy('id')
              ->toArray();
      }

Finally setup the filter

          SmartSelectFilter::make('Country', 'cuntry')
              ->config(['displayHtmlName' => true])
              ->options(
                  $this->arrayOfCountries
              )
              ->filter(function (Builder $builder, array $values) {
                  $builder->whereIn('country_id', $values);
              }),
Clone this wiki locally