One complete allocation
Neighboring weights change together. The total remains 100%.
Dynamic variants
Link segments to repeater rows and keep their count in sync.
First allocation
Add the field to your form schema:[34, 33, 33]. The default minimum is 12% per segment. Labels follow the array order; without custom labels, the field shows 1, 2, 3, and so on.
Segment count and initial weights
- Two options
- Four options
- Five options
segmentCount() supports 2–5 segments. Direct PHP values outside this range are clamped to the nearest supported count. Supply exactly that many integer weights, each at least minWeight(), with a total of 100. default() applies to a new form; editing an existing record uses its saved allocation.
Without default(), the field distributes weights equally. Any remaining percentage points go to the first segments: three options start at [34, 33, 33], and four at [25, 25, 25, 25].
Appearance
Variants
default uses bordered segments. secondary uses a filled surface. Both support the panel’s light and dark modes. These are the two supported variant names.
Three sizes
md. You can also pass ControlSize::Sm, ControlSize::Md or ControlSize::Lg from Bjanczak\FilamentFlexFields\Enums\ControlSize.
Custom labels
labels(null):
Percentage visibility
minWeight() + 1 and at most 100.
On very narrow segments, the percentage also hides when there is insufficient room, so the segment number is not squeezed. The divider’s accessible description still includes both neighboring labels and weights.
Minimum weights and locked segments
Set the minimum
minWeight(5) prevents any weight from dropping below 5%. Whole percentage points are used throughout. Zero-weight segments are not supported; the lowest effective minimum is 1%.
Lock a weight in the interface
[1] locks the second segment. Both dividers touching it are disabled. In this example, C and D can still exchange weight. A divider cannot move if either neighboring segment is locked. Duplicate indices are ignored, and indices outside the segment count are discarded.
Clear the locks with lockedSegments([]).
Locks control interaction. If a percentage must be fixed by your business rules, validate that requirement on the server too; a browser restriction is not an authorization rule.
Enforce a fixed percentage on the server
Disable the field
->dehydrated() only when you intentionally want that state included in the submitted data; server-side validation still applies.
Link to repeater rows
Use a repeater when the user can add and remove variants. Create the allocation once and attach its synchronization callback to the repeater:- Adding or removing a row distributes the weights equally across the new count.
- Editing a row’s URL preserves the current allocation.
- By default, the allocation is hidden below two rows and uses numbered labels.
- Keep the repeater at a maximum of five rows. Linked allocations outside 2–5 rows fail validation when submitted.
- Segment weights follow row order. Disable reordering, as above, when weights must retain their association with individual rows. If you enable reordering, manage the allocation-to-row association in your application.
Custom labels and visibility threshold
numericLabels: false retains your custom labels. minimumItems: 3 shows the field only when three or more rows exist; supported visibility thresholds are 2–5. This is a visibility setting, not a repeater minimum rule. Add minItems(3) to the repeater if three rows are mandatory.
The state path is relative to the allocation’s container. If both fields are nested in a repeater row or group, use the path to the repeater from that same context. For a linked allocation, the row count determines the segment count, replacing a separately configured segmentCount().
Dynamic configuration
The component-specific count, minimum, threshold, variant, labels and locks accept closures. Size accepts a string,ControlSize or a closure. Closure arguments use Filament’s utility injection.
live() so configuration changes reach the server and rerender the allocation. Changing the segment count recovers an allocation for the new count. Keep the minimum feasible for every possible count.
linkedToRepeater() accepts a string or closure for its path; numericLabels and minimumItems are fixed arguments.
Validation and database storage
Built-in validation
Validation runs when the form is submitted. A valid allocation is an ordered list with:- exactly the configured number of weights;
- integer percentages between
minWeight()and 100; - a total of exactly 100;
- a supported linked repeater count, when configured.
'25' are converted to integers.
required() when an allocation is mandatory. Standard Filament rules, labels, helper text and state-binding options are available. Add business validation with rules() as shown above.
Loading existing values
Initial hydration can recover an invalid saved allocation to an equal split or redistribute available weight across unlocked segments. That recovery is separate from submission validation: a forged payload is rejected rather than silently repaired during save.Save to a JSON column
The field stores a list such as[50, 25, 25]. Use a JSON column and an Eloquent array cast:
$this->form->getState() before saving it. Do not persist unvalidated public properties directly.
Keyboard, touch and change events
Touch and pen use the same dividers as the mouse. Track measurements adjust to scroll and resize during a gesture. Locked and disabled dividers are skipped by keyboard focus.
The view updates while dragging, and one complete allocation is committed when the gesture ends. Keyboard changes commit immediately. Deferred binding waits for the form’s next request;
live() requests a server update after a committed change, rather than after every pointer movement.
input and change events with event.detail.weights after a committed change:
linkedToRepeater() defaults to deferred allocation binding. Call live() after it if you explicitly need a server callback on each completed allocation change.
Configuration reference
Inherited form options include
default(), required(), rules(), disabled(), label(), helperText(), columnSpanFull(), live() and afterStateUpdated(). These follow the normal Filament form API.
FLEX schema configuration
Usetraffic_split as the schema type. traffic-split is the catalog route and asset identifier, not the saved schema type.
config keys map to the PHP options above. linked_repeater is a relative repeater path; leave it null for a standalone field. Set up the repeater callback and partial rendering in the containing form, as in the repeater example. Labels, defaults and required status are field-level properties outside config.
Related components
FlexSlider
One value or a pair of bounds on a numeric scale.
TrackSlider
A single numeric value on a compact track.
ProgressBar
Display a percentage without editing it.