Support

Account

Home Forums Add-ons Repeater Field Avoid duplicate content on repeater field Reply To: Avoid duplicate content on repeater field

  • Thanks for this suggestion @hube2 – this is a nice piece of functionality.

    I made some tweaks for my use case, pasted here in case useful to anyone. In my case, I want to be able to check that the first field of each the repeater is unique – I don’t care what happens to the others. This way the field becomes a key.

    NB this doesn’t currently work for nested repeaters-in-repeaters. One day I may try to tackle that.

    The main function is here:

    add_filter('acf/validate_value/type=repeater', 'grly_acf_validate_repeater', 10, 4);
    
    function grly_acf_validate_repeater($valid, $value, $field, $input) {
    
    	if (!$valid || !$field['preventduplicates']) {
    		return $valid;
    	}
    
    	// get list of array indexes from $input
    	// [ <= this fixes my IDE, it has problems with unmatched brackets
    	preg_match_all('/\[([^\]]+)\]/', $input, $matches);
    	if (!count($matches[1])) {
    		// this should actually never happen
    		return $valid;
    	}
    	$matches = $matches[1];
    
    	// walk the acf input to find the repeater and current row
    	$array = $_POST['acf'];
    
    	$field_key = false;
    	$field_value = false;
    
    	for ($i = 0; $i < count($matches); $i++) {
    		if (isset($array[$matches[$i]])) {
    
    			$field_key = $matches[$i];
    			$field_value = $array[$matches[$i]];
    
    			if ($field_key == $field['key']) {
    				break;
    			}
    			$array = $field_value;
    
    		}
    	}
    
    	$used = [];
    	foreach ($field_value as $index => $row) {
    		$first_entry = reset($row); // Extracts the first entry in the object for that row;
    		if ($first_entry) {
    			if (!in_array($first_entry, $used)) {
    				$used[] = $first_entry;
    			} else {
    				$valid = 'The value ' . $first_entry . ' is used more than once. The first field in this repeater must be unique across the repeater.';
    				break;
    			}
    		}
    	}
    
    	return $valid;
    }
    

    … then I’ve added a ‘prevent duplicates’ field to all repeaters so that it can be toggled on and off:

    add_action('acf/render_field_settings/type=repeater', 'add_no_duplicates_field_to_repeater');
    function add_no_duplicates_field_to_repeater($field) {
    	acf_render_field_setting($field, [
    		'label' => __('Prevent duplicates?', 'acf'),
    		'instructions' => 'Prevents rows being saved where the first value is the same as that in another row',
    		'type' => 'radio',
    		'name' => 'preventduplicates',
    		'choices' => array(
    			1 => __("Yes", 'acf'),
    			0 => __("No", 'acf'),
    		),
    		'default_value' => 0,
    		'layout' => 'horizontal',
    	]);
    
    }