Package Data | |
---|---|
Maintainer Username: | Tarpsvo |
Maintainer Contact: | tarvoreinpalu@gmail.com (Tarvo Reinpalu) |
Package Create Date: | 2019-05-09 |
Package Last Update: | 2024-10-31 |
Home Page: | |
Language: | PHP |
License: | MIT |
Last Refreshed: | 2024-11-09 15:08:44 |
Package Statistics | |
---|---|
Total Downloads: | 1,395,403 |
Monthly Downloads: | 76,332 |
Daily Downloads: | 2,504 |
Total Stars: | 333 |
Total Watchers: | 12 |
Total Forks: | 120 |
Total Open Issues: | 30 |
This Laravel Nova package adds a multiselect to Nova's arsenal of fields.
php: >=8.1
laravel/nova: ^4.1
Install the package in a Laravel Nova project via Composer:
composer require outl1ne/nova-multiselect-field
The field is used similarly to Nova's native Select field. The field type in the database should be text-based (ie string
, text
or varchar
), selected values are stored as a stringified JSON array.
use Outl1ne\MultiselectField\Multiselect;
public function fields(Request $request)
{
return [
Multiselect::make('Football teams')
->options([
'liverpool' => 'Liverpool FC',
'tottenham' => 'Tottenham Hotspur',
])
// Optional:
->placeholder('Choose football teams') // Placeholder text
->max(4) // Maximum number of items the user can choose
->saveAsJSON() // Saves value as JSON if the database column is of JSON type
->optionsLimit(5) // How many items to display at once
->reorderable() // Allows reordering functionality
->singleSelect() // If you want a searchable single select field
->distinct('football') // Disables values used by other multiselects in same distinct group
->taggable() // Possible to add values ("tags") on the fly
// Async model querying
Multiselect::make('Artists')
->asyncResource(Artist::class),
// If you want a custom search, create your own endpoint:
->api('/api/multiselect/artists?something=false', Artist::class),
];
}
Option groups are supported. Their syntax is the same as Laravel's option group syntax.
In this example (from Nova docs), all values are grouped by the group
key:
->options([
'MS' => ['label' => 'Small', 'group' => 'Men Sizes'],
'MM' => ['label' => 'Medium', 'group' => 'Men Sizes'],
'WS' => ['label' => 'Small', 'group' => 'Women Sizes'],
'WM' => ['label' => 'Medium', 'group' => 'Women Sizes'],
])
You can make a Multiselect depend on another by using dependsOn
. This also requires specifying ->dependsOnOptions()
. The value from the dependsOn
Multiselect has to be the key to the options and the value must be a key-value dictionary of options as usual.
Usage:
Multiselect::make('Country', 'country')
->options([
'IT' => 'Italy',
'SG' => 'Singapore',
]),
Multiselect::make('Language', 'language')
->dependsOn('country')
->dependsOnOptions([
'IT' => [
'it' => 'Italian',
],
'SG' => [
'en' => 'English',
'ms' => 'Malay',
'zh' => 'Chinese',
]
]),
// Optionally define max number of values
->dependsOnMax([
'IT' => 1,
'SG' => 3,
])
You can use this field for BelongsToMany
relationship selection.
// Add your BelongsToMany relationship to your model:
public function categories()
{
return $this->belongsToMany(\App\Models\Category::class);
}
// Add the field to your Resource for asynchronous option querying:
Multiselect::make('Categories', 'categories')
->belongsToMany(\App\Nova\Resources\Category::class),
// Alternatively, you can set the second argument to 'false' to
// query the options on page load and prevent the user from having
// to first type in order to view the available options. Note: Not
// recommended for unbounded relationship row counts.
Multiselect::make('Categories', 'categories')
->belongsToMany(\App\Nova\Resources\Category::class, false),
Possible options you can pass to the field using the option name as a function, ie ->placeholder('Choose peanuts')
.
| Option | type | default | description |
| -------------------------- | ------------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| options
| Array|callable | [] | Options in an array as key-value pairs (['id' => 'value']
). |
| api($path, $resource)
| String, String (Resource) | null | URL that can be used to fetch options asynchronously. The search string is provided in the search
query parameter. The API must return object containing key-value pairs (['id' => 'value']
). |
| asyncResource($resource)
| String (Resource) | null | Provide a Resource class to fetch the options asynchronously. |
| placeholder
| String | Field name | The placeholder string for the input. |
| max
| Number | Infinite | The maximum number of options a user can select. |
| groupSelect
| Boolean | false | For use with option groups - allows the user to select whole groups at once |
| singleSelect
| Boolean | false | Makes the field act as a single select which also means the saved value will not be an array. |
| saveAsJSON
| Boolean | false | When you have a SQL JSON column, you can force the field to save the values as JSON. By default, values are saved as a stringified array. |
| optionsLimit
| Number | 1000 | The maximum number of options displayed at once. Other options are still accessible through searching. |
| nullable
| Boolean | false | If the field is nullable an empty select will result in null
else an empty array ([]
) is stored. |
| reorderable
| Boolean | false | Enables (or disables) the reordering functionality of the multiselect field. |
| dependsOn
| String | null | Determines which Multiselect this field depends on. |
| dependsOnOptions
| Array | null | Determines the options for dependsOn
. See example above on how to format it correctly. |
| belongsToMany
| String (Resource) | null | Allows the Multiselect to function as a BelongsToMany field. |
| belongsTo
| String (Resource) | null | Allows the Multiselect to function as a BelongsTo field. |
| taggable
| Boolean | false | Makes the Multiselet to support tags (dynamically entered values). |
| clearOnSelect
| Boolean | false | Clears input after an option has been selected. |
| distinct
| String | Field Attribute | Syncs options between multiple multiselects in the same group and disables the options that have already been used. |
| indexDelimiter
| String | ', '
| Sets delimiter used to join values on index view |
| indexValueDisplayLimit
| Number | 9999 | Define how many values can be displayed at once on index view |
| indexCharDisplayLimit
| Number | 40 | Set char limit for index display value |
The translations file can be published by using the following publish command:
php artisan vendor:publish --provider="Outl1ne\MultiselectField\FieldServiceProvider" --tag="translations"
You can then edit the strings to your liking.
You can overwrite the detail view value component to customize it as you see fit.
Create a new component for NovaMultiselectDetailFieldValue
and register it in your app.js
. The component receives two props: field
and values
. The values
prop is an array of selected labels.
// in NovaMultiselectDetailFieldValue.vue
<template>
<div class="relative rounded-lg bg-white shadow border border-60" v-if="values">
<div class="overflow-hidden rounded-b-lg rounded-t-lg">
<div class="border-b border-50 cursor-text font-mono text-sm py-2 px-4" v-for="(value, i) of values" :key="i">
{{ value }}
</div>
</div>
</div>
<div v-else>—</div>
</template>
<script>
export default {
props: ['field', 'values'],
};
</script>
// in app.js
import NovaMultiselectDetailFieldValue from './NovaMultiselectDetailFieldValue';
Nova.booting((Vue, router, store) => {
Vue.component('nova-multiselect-detail-field-value', NovaMultiselectDetailFieldValue);
});
This project is open-sourced software licensed under the MIT license.