滑块
简介
滑块组件允许你在轨道上拖动手柄,以选择一个或多个数值:
use Filament\Forms\Components\Slider;
Slider::make('slider')

该组件使用 noUiSlider 包,其大部分 API 均基于该库。
WARNING
就其本质而言,滑块字段永远不能为空。字段值永远不能是 null 或空数组。若滑块字段为空,用户将没有可在轨道上拖动的手柄。
因此,滑块字段开箱即有默认值,该值设为滑块 范围 内允许的最小值。当表单为空时会使用该默认值,例如资源的创建(Create)页面。要了解更多关于默认值的信息,请参阅 default() 文档。
控制滑块的范围
默认情况下,滑块可选的最小值与最大值分别为 0 和 100。Filament 会自动应用验证规则,确保用户无法超出这些值。你可以用 range() 方法调整它们:
use Filament\Forms\Components\Slider;
Slider::make('slider')
->range(minValue: 40, maxValue: 80)TIP
除了接受静态值,range() 方法也接受函数以动态计算这些值。你可以将各种工具(utilities)作为参数注入到函数中。


控制步长
默认情况下,用户可在最小值与最大值之间选择任意小数值。你可以使用 step() 方法将可选值限制为特定步长。Filament 会自动应用验证规则,确保用户无法偏离该步长:
use Filament\Forms\Components\Slider;
Slider::make('slider')
->range(minValue: 0, maxValue: 100)
->step(10)TIP
除了接受静态值,step() 方法也接受函数以动态计算该值。你可以将各种工具(utilities)作为参数注入到函数中。
限制小数位数
若你更希望允许用户在最小值与最大值之间选择任意小数值,而不是将其限制为某一固定步长,可以使用 decimalPlaces() 方法定义所选值将四舍五入到的小数位数:
use Filament\Forms\Components\Slider;
Slider::make('slider')
->range(minValue: 0, maxValue: 100)
->decimalPlaces(2)TIP
除了接受静态值,decimalPlaces() 方法也接受函数以动态计算该值。你可以将各种工具(utilities)作为参数注入到函数中。
控制轨道的行为内边距
默认情况下,用户可在整条轨道上选择任意值。你可以使用 rangePadding() 方法为轨道添加行为内边距。这将确保所选值始终与轨道边缘至少保持一定距离。Filament 默认应用于滑块的最小值与最大值验证会将该内边距纳入考量,确保用户无法超出加了内边距后的范围:
use Filament\Forms\Components\Slider;
Slider::make('slider')
->range(minValue: 0, maxValue: 100)
->rangePadding(10)TIP
除了接受静态值,rangePadding() 方法也接受函数以动态计算该值。你可以将各种工具(utilities)作为参数注入到函数中。


在此示例中,尽管最小值为 0、最大值为 100,用户只能选择 10 到 90 之间的值。内边距会应用于轨道两端,因此所选值始终与轨道边缘至少相距 10 个单位。
若希望分别控制轨道两侧的内边距,可以向 rangePadding() 方法传入包含两个值的数组。第一个值应用于轨道起点,第二个值应用于轨道终点:
use Filament\Forms\Components\Slider;
Slider::make('slider')
->range(minValue: 0, maxValue: 100)
->rangePadding([10, 20])从右到左的轨道
默认情况下,轨道按从左到右运作。若用户使用从右到左的区域设置(例如阿拉伯语),轨道会自动按从右到左显示。你也可以使用 rtl() 方法强制轨道按从右到左显示:
use Filament\Forms\Components\Slider;
Slider::make('slider')
->range(minValue: 0, maxValue: 100)
->rtl()可选地,你可以传入一个布尔值,以控制滑块是否应为从右到左:
use Filament\Forms\Components\Slider;
Slider::make('slider')
->range(minValue: 0, maxValue: 100)
->rtl(FeatureFlag::active())TIP
除了接受静态值,rtl() 方法也接受函数以动态计算该值。你可以将各种工具(utilities)作为参数注入到函数中。


为滑块添加多个值
若滑块被设为一个值数组,用户即可在允许范围内沿轨道拖动多个手柄。请确保滑块有一个设为值数组的 default() 值,以便在表单为空时使用:
use Filament\Forms\Components\Slider;
Slider::make('slider')
->range(minValue: 0, maxValue: 100)
->default([20, 70])

若你使用 Eloquent 保存多个滑块值,应确保为模型属性添加 array 类型转换(cast):
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
/**
* @return array<string, string>
*/
protected function casts(): array
{
return [
'slider' => 'array',
];
}
// ...
}使用垂直轨道
你可以使用 vertical() 方法将滑块显示为垂直轨道而非水平轨道:
use Filament\Forms\Components\Slider;
Slider::make('slider')
->range(minValue: 0, maxValue: 100)
->vertical()

可选地,你可以传入一个布尔值,以控制滑块是否应为垂直:
use Filament\Forms\Components\Slider;
Slider::make('slider')
->range(minValue: 0, maxValue: 100)
->vertical(FeatureFlag::active())TIP
除了接受静态值,vertical() 方法也接受函数以动态计算该值。你可以将各种工具(utilities)作为参数注入到函数中。
从上到下的轨道
默认情况下,垂直轨道按从下到上运作。在 noUiSlider 中,这对应 从右到左行为。要将最小值置于轨道顶部,可以使用 rtl(false) 方法:
use Filament\Forms\Components\Slider;
Slider::make('slider')
->range(minValue: 0, maxValue: 100)
->vertical()
->rtl(false)

为手柄添加工具提示
你可以使用 tooltips() 方法为滑块手柄添加工具提示。工具提示会显示手柄的当前值:
use Filament\Forms\Components\Slider;
Slider::make('slider')
->range(minValue: 0, maxValue: 100)
->tooltips()

可选地,你可以传入一个布尔值,以控制滑块是否应显示工具提示:
use Filament\Forms\Components\Slider;
Slider::make('slider')
->range(minValue: 0, maxValue: 100)
->tooltips(FeatureFlag::active())使用多个手柄时,会显示多个工具提示,每个手柄各一个。工具提示也适用于 垂直轨道。


自定义工具提示格式
你可以使用 JavaScript 自定义工具提示的格式。向 tooltips() 方法传入一个包含 JavaScript 字符串表达式的 RawJs 对象。待格式化的当前值可在 $value 变量中获取:
use Filament\Forms\Components\Slider;
use Filament\Support\RawJs;
Slider::make('slider')
->range(minValue: 0, maxValue: 100)
->tooltips(RawJs::make(<<<'JS'
`$${$value.toFixed(2)}`
JS))

分别控制多个手柄的工具提示
若滑块被设为一个值数组,你可以通过向 tooltips() 方法传入值数组,分别控制每个手柄的工具提示。第一个值应用于第一个手柄,第二个值应用于第二个手柄,以此类推:
use Filament\Forms\Components\Slider;
Slider::make('slider')
->range(minValue: 0, maxValue: 100)
->tooltips([true, false])

用颜色填充轨道
默认情况下,轨道颜色不受其上任何手柄位置的影响。使用单个手柄时,你可以使用 fillTrack() 方法用颜色填充手柄之前的轨道部分:
use Filament\Forms\Components\Slider;
Slider::make('slider')
->range(minValue: 0, maxValue: 100)
->fillTrack()

可选地,你可以传入一个布尔值,以控制滑块是否应填充:
use Filament\Forms\Components\Slider;
Slider::make('slider')
->range(minValue: 0, maxValue: 100)
->fillTrack(FeatureFlag::active())TIP
除了接受静态值,fillTrack() 方法也接受函数以动态计算该值。你可以将各种工具(utilities)作为参数注入到函数中。
使用多个手柄时,你必须通过传入 true 与 false 值的数组手动指定应填充轨道的哪些部分,每个区段各一个值。值的总数应比手柄数量多一个。第一个值应用于第一个手柄之前的区段,第二个值应用于第一与第二个手柄之间的区段,以此类推:
use Filament\Forms\Components\Slider;
Slider::make('slider')
->range(minValue: 0, maxValue: 100)
->fillTrack([false, true, false])

填充同样适用于 垂直轨道:


为轨道添加刻度标记
你可以为轨道添加刻度标记(pips),它们是指示手柄位置的小标记。你可以使用 pips() 方法为轨道添加刻度标记:
use Filament\Forms\Components\Slider;
Slider::make('slider')
->range(minValue: 0, maxValue: 100)
->pips()

存在多个手柄时,刻度标记同样有效:


你也可以为 垂直轨道 添加刻度标记:


调整刻度标记密度
默认情况下,刻度标记的密度为 10。这意味着轨道上每 10 个单位会显示一个刻度标记。你可以使用 pips() 方法的 density 参数调整该密度:
use Filament\Forms\Components\Slider;
Slider::make('slider')
->range(minValue: 0, maxValue: 100)
->pips(density: 5)TIP
除了接受静态值,density 参数也接受函数以动态计算该值。你可以将各种工具(utilities)作为参数注入到函数中。


自定义刻度标记标签格式
你可以使用 JavaScript 自定义刻度标记标签的格式。向 pipsFormatter() 方法传入一个包含 JavaScript 字符串表达式的 RawJs 对象。待格式化的当前值可在 $value 变量中获取:
use Filament\Forms\Components\Slider;
use Filament\Support\RawJs;
Slider::make('slider')
->range(minValue: 0, maxValue: 100)
->pips()
->pipsFormatter(RawJs::make(<<<'JS'
`$${$value.toFixed(2)}`
JS))TIP
除了接受静态值,pipsFormatter() 方法也接受函数以动态计算该值。你可以将各种工具(utilities)作为参数注入到函数中。


为轨道步长添加刻度标记标签
若你使用 步长 限制轨道上的移动,可以为每个步长添加刻度标记标签。为此,向 pips() 方法传入 PipsMode::Steps 对象:
use Filament\Forms\Components\Slider;
use Filament\Forms\Components\Slider\Enums\PipsMode;
Slider::make('slider')
->range(minValue: 0, maxValue: 100)
->step(10)
->pips(PipsMode::Steps)

若希望在轨道上再添加不带标签的额外刻度标记,也可以 调整刻度标记密度:
use Filament\Forms\Components\Slider;
use Filament\Forms\Components\Slider\Enums\PipsMode;
Slider::make('slider')
->range(minValue: 0, maxValue: 100)
->step(10)
->pips(PipsMode::Steps, density: 5)

在轨道的百分比位置添加刻度标记标签
若希望在轨道的特定百分比位置添加刻度标记标签,可以向 pips() 方法传入 PipsMode::Positions 对象。百分比位置需在 pipsValues() 方法中以数字数组定义:
use Filament\Forms\Components\Slider;
use Filament\Forms\Components\Slider\Enums\PipsMode;
Slider::make('slider')
->range(minValue: 0, maxValue: 100)
->pips(PipsMode::Positions)
->pipsValues([0, 25, 50, 75, 100])TIP
除了接受静态值,pipsValues() 方法也接受函数以动态计算这些值。你可以将各种工具(utilities)作为参数注入到函数中。


密度 仍控制不带标签的刻度标记间距。
在轨道上添加固定数量的刻度标记标签
若希望在轨道上添加固定数量的刻度标记标签,可以向 pips() 方法传入 PipsMode::Count 对象。刻度标记数量需在 pipsValues() 方法中定义:
use Filament\Forms\Components\Slider;
use Filament\Forms\Components\Slider\Enums\PipsMode;
Slider::make('slider')
->range(minValue: 0, maxValue: 100)
->pips(PipsMode::Count)
->pipsValues(5)TIP
除了接受静态值,pipsValues() 方法也接受函数以动态计算这些值。你可以将各种工具(utilities)作为参数注入到函数中。


密度 仍控制不带标签的刻度标记间距。
在轨道的指定值处添加刻度标记标签
除了定义 百分比位置 或 固定数量 的刻度标记标签,你也可以定义一组用于刻度标记标签的值。为此,向 pips() 方法传入 PipsMode::Values 对象。这些值需在 pipsValues() 方法中以数字数组定义:
use Filament\Forms\Components\Slider;
use Filament\Forms\Components\Slider\Enums\PipsMode;
Slider::make('slider')
->range(minValue: 0, maxValue: 100)
->pips(PipsMode::Values)
->pipsValues([5, 15, 25, 35, 45, 55, 65, 75, 85, 95])TIP
除了接受静态值,pipsValues() 方法也接受函数以动态计算这些值。你可以将各种工具(utilities)作为参数注入到函数中。


密度 仍控制不带标签的刻度标记间距:
use Filament\Forms\Components\Slider;
use Filament\Forms\Components\Slider\Enums\PipsMode;
Slider::make('slider')
->range(minValue: 0, maxValue: 100)
->pips(PipsMode::Values, density: 5)
->pipsValues([5, 15, 25, 35, 45, 55, 65, 75, 85, 95])

手动过滤刻度标记
若要对轨道上刻度标记的显示方式有更精细的控制,可以使用 JavaScript 表达式。该表达式应根据刻度标记的外观返回不同数字:
- 若应显示大刻度标记标签,表达式应返回 `1`。
- 若应显示小刻度标记标签,表达式应返回 `2`。
- 若应显示不带标签的刻度标记,表达式应返回 `0`。
- 若完全不显示刻度标记,表达式应返回 `-1`。
刻度标记的 密度 会控制哪些值会传给 JavaScript 表达式。表达式应使用 $value 变量访问当前刻度标记的值。表达式应定义在 RawJs 对象中并传给 pipsFilter() 方法:
use Filament\Forms\Components\Slider;
use Filament\Support\RawJs;
Slider::make('slider')
->range(minValue: 0, maxValue: 100)
->pips(density: 5)
->pipsFilter(RawJs::make(<<<'JS'
($value % 50) === 0
? 1
: ($value % 10) === 0
? 2
: ($value % 25) === 0
? 0
: -1
JS))TIP
除了接受静态值,pipsFilter() 方法也接受函数以动态计算该值。你可以将各种工具(utilities)作为参数注入到函数中。
在此示例中,使用 % 运算符判断刻度标记值的可整除性。表达式对每 50 个单位返回 1,每 10 个单位返回 2,每 25 个单位返回 0,其余值返回 -1:


设置手柄之间的最小差值
要设置手柄之间的最小距离,可以使用 minDifference() 方法并传入一个数字。这表示两个手柄值之间的实际差值,而非视觉距离:
use Filament\Forms\Components\Slider;
Slider::make('slider')
->range(minValue: 0, maxValue: 100)
->minDifference(10)TIP
除了接受静态值,minDifference() 方法也接受函数以动态计算该值。你可以将各种工具(utilities)作为参数注入到函数中。
WARNING
minDifference() 方法不影响滑块的验证。熟练用户可能通过 JavaScript 操纵滑块值,选择不符合最小差值的值。他们仍无法选择超出滑块范围的值。
设置手柄之间的最大差值
要设置手柄之间的最大距离,可以使用 maxDifference() 方法并传入一个数字。这表示两个手柄值之间的实际差值,而非视觉距离:
use Filament\Forms\Components\Slider;
Slider::make('slider')
->range(minValue: 0, maxValue: 100)
->maxDifference(40)TIP
除了接受静态值,maxDifference() 方法也接受函数以动态计算该值。你可以将各种工具(utilities)作为参数注入到函数中。
WARNING
maxDifference() 方法不影响滑块的验证。熟练用户可能通过 JavaScript 操纵滑块值,选择不符合最大差值的值。他们仍无法选择超出滑块范围的值。
控制滑块的一般行为
滑块的 behavior() 方法允许你传入一个或多个 Behavior 对象以控制滑块行为。可用选项包括:
- `Behavior::Tap` - 用户点击轨道时,滑块会平滑移动到点击位置。这是默认行为,因此在应用其他行为时,若想保留该行为,也应将其包含在数组中。
- `Behavior::Drag` - 当轨道上有两个手柄时,用户可拖动轨道以同时移动两个手柄。必须使用 [`fillTrack([false, true, false])`](#filling-a-track-with-color) 方法,以确保用户有可拖动的区域。
- `Behavior::Drag` 与 `Behavior::Fixed` - 当轨道上有两个手柄时,用户可拖动轨道以同时移动两个手柄,但无法改变它们之间的距离。必须使用 [`fillTrack([false, true, false])`](#filling-a-track-with-color) 方法,以确保用户有可拖动的区域。请注意,手柄之间的距离不会在后端自动验证,因此熟练用户可能通过 JavaScript 操纵滑块值,选择不同距离的值。他们仍无法选择超出滑块范围的值。
- `Behavior::Unconstrained` - 当轨道上有多个手柄时,它们可以相互越过拖动。[`minDifference()`](#setting-a-minimum-difference-between-handles) 与 [`maxDifference()`](#setting-a-maximum-difference-between-handles) 方法在此行为下无效。
- `Behavior::SmoothSteps` - 拖动手柄时,它们不会吸附到轨道的 [步长](#controlling-the-step-size)。用户松开手柄后,它会吸附到最近的步长。
例如,要同时使用 Behavior::Tap、Behavior::Drag 与 Behavior::SmoothSteps:
use Filament\Forms\Components\Slider;
use Filament\Forms\Components\Slider\Enums\Behavior;
Slider::make('slider')
->range(minValue: 0, maxValue: 100)
->behavior([Behavior::Tap, Behavior::Drag, Behavior::SmoothSteps])要禁用所有行为(包括默认的 Behavior::Tap),可以使用 behavior(null) 方法:
use Filament\Forms\Components\Slider;
Slider::make('slider')
->range(minValue: 0, maxValue: 100)
->behavior(null)非线性轨道
你可以通过在滑块的 nonLinearPoints() 方法中定义百分比点数组,创建某些部分被压缩或拉伸的非线性轨道。数组中每个百分比键应有对应的实际值,用于计算手柄在轨道上的位置。下面的示例配合 刻度标记 演示轨道的非线性行为:
use Filament\Forms\Components\Slider;
Slider::make('slider')
->range(minValue: 0, maxValue: 100)
->nonLinearPoints(['20%' => 50, '50%' => 75])
->pips()

TIP
除了接受静态值,nonLinearPoints() 方法也接受函数以动态计算这些值。你可以将各种工具(utilities)作为参数注入到函数中。
使用非线性轨道时,你还可以控制每个区段的步进。通过为每个百分比点定义包含两个数字的数组,第一个数字用作该百分比位置的实际值,第二个数字用作该区段的步长,直至下一个百分比点为止有效:
use Filament\Forms\Components\Slider;
Slider::make('slider')
->range(minValue: 0, maxValue: 100)
->nonLinearPoints(['20%' => [50, 5], '50%' => [75, 1]])
->pips()WARNING
使用非线性轨道时,某些轨道区段的步长值不影响滑块的验证。熟练用户可能通过 JavaScript 操纵滑块值,选择与轨道步长值不一致的值。他们仍无法选择超出滑块范围的值。
在非线性轨道上使用 刻度标记 时,你可以确保刻度标记标签被四舍五入,并仅显示在轨道上可选的位置。否则,非线性区段的步进可能在不可选位置添加标签。为此,使用 steppedPips() 方法:
use Filament\Forms\Components\Slider;
use Filament\Forms\Components\Slider\Enums\PipsMode;
Slider::make('slider')
->range(minValue: 0, maxValue: 10000)
->nonLinearPoints(['10%' => [500, 500], '50%' => [4000, 1000]])
->pips(PipsMode::Positions, density: 4)
->pipsValues([0, 25, 50, 75, 100])
->steppedPips()