How to prevent already selected value in repeater?

I am using repeater to add working hours and I don't want users to select same day twice. How can I prevent this?
12 Replies
toeknee
toeknee2y ago
Are you using a select in the repeater? The only way I can think of is to get the variables in the repeater and query them on a custom rule
Darpan
DarpanOP2y ago
Yes, I am using select in the repeater. Can you please show how?
toeknee
toeknee2y ago
IIRC you can call the repeater name to get the array of elements with a closure in rules and pass it in to validate itv
Garadit
Garadit2y ago
Has the problem been resolved? I'm a bit lost on how to do that for Select Columns
toeknee
toeknee2y ago
So you would have to go through all the fields with a closure and check their values to ensure it’s not been selected.
Garadit
Garadit2y ago
I just want it to work like multiselect, which doesn't show the selection when it's already selected in another repeater. If using rules, won't it check it after the form is submitted (clicked submit)?
awcodes
awcodes2y ago
Validation is your best bet here. Think about it. A repeater uses the same fields when a new item is added, so if you remove an option from the select then it will no longer exist as an option in the places it’s already been set nulling those out.
Garadit
Garadit2y ago
Make sense now
Darpan
DarpanOP2y ago
I am doing this like below, this may not be perfect solution but its working for me. Repeater:
TableRepeater::make('working_hours')->schema([
Select::make('day')
->disableLabel()
->required()
->rule('required')
->options(
fn($state, $get) => VcardFormHelper::getDays($state, $get)
),

// other fields
])
->createItemButtonLabel('Add working hours')
->defaultItems(0)
->maxItems(7)
->disableLabel(),
TableRepeater::make('working_hours')->schema([
Select::make('day')
->disableLabel()
->required()
->rule('required')
->options(
fn($state, $get) => VcardFormHelper::getDays($state, $get)
),

// other fields
])
->createItemButtonLabel('Add working hours')
->defaultItems(0)
->maxItems(7)
->disableLabel(),
Get days:
public static function getDays(string|null $state, Closure $get): array
{
// All days
$days = [
'monday' => 'Monday',
'tuesday' => 'Tuesday',
'wednesday' => 'Wednesday',
'thursday' => 'Thursday',
'friday' => 'Friday',
'saturday' => 'Saturday',
'sunday' => 'Sunday',
];

// Get all repeater items
$workingHours = $get('../../working_hours');

// Retrieve days from repeater items
$existing = array_column($workingHours, 'day');

// Remove null days
$existing = array_filter($existing);

// Remove all existing options from days
$options = array_diff_key($days, array_flip($existing));

// Check if current option is not null
if ($state !== null) {
// Add current state to items and return
return array_merge($options, [$state => $days[$state]]);
}

return $options;
}
public static function getDays(string|null $state, Closure $get): array
{
// All days
$days = [
'monday' => 'Monday',
'tuesday' => 'Tuesday',
'wednesday' => 'Wednesday',
'thursday' => 'Thursday',
'friday' => 'Friday',
'saturday' => 'Saturday',
'sunday' => 'Sunday',
];

// Get all repeater items
$workingHours = $get('../../working_hours');

// Retrieve days from repeater items
$existing = array_column($workingHours, 'day');

// Remove null days
$existing = array_filter($existing);

// Remove all existing options from days
$options = array_diff_key($days, array_flip($existing));

// Check if current option is not null
if ($state !== null) {
// Add current state to items and return
return array_merge($options, [$state => $days[$state]]);
}

return $options;
}
toeknee
toeknee2y ago
Good work
Garadit
Garadit2y ago
This is working very well, thank you
DianaMujoiu
DianaMujoiu11mo ago
Hello, regarding this implementation, does the first select retain its selection when you add a new item? Because when I add a new item, the first selection disappears

Did you find this page helpful?