Support

Account

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

Solved

Avoid duplicate content on repeater field

  • Hi guys! And tnxs for the awesome pluigns thats is saving me every day!

    The doubt I have is quite simple…
    That is a way to avoid the duplicate content on the repeater field?
    I’m breaking my mind trying to think in a way, but somes ideas could be good in this point.

    Note: I wanna avoid the duplication in the back end, for user do not put som equals content or some equals type of content. For example, social networks, a repeat that register all social networks of a company, but i dont want 2 facebooks, and u know people do that!

    Tnks for now… and waiting for a light.

  • I’ve recently had to do this myself, otherwise I could not give you an answer. This probably took me a few hours to work out.

    This function will validate any repeater sub field to make sure it’s unique across all rows. Please note that this code is a little obtuse and not easy to follow. It would probably take me several pages to explain what it’s doing, but I hope it helps.

    In this case you need to use the field key version of the acf/validate_value filter https://www.advancedcustomfields.com/resources/acf-validate_value/

    
    add_filter('acf/validate_value/key='.$field_key, 'unique_repeater_sub_field', 20, 4);
    

    Here is the function

    
    function unique_repeater_sub_field($valid, $value, $field, $input) {
      if (!$valid) {
        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'];
      
      $repeater_key = false;
      $repeater_value = false;
      $row_key = false;
      $row_value = false;
      $field_key = false;
      $field_value = false;
      
      for ($i=0; $i<count($matches); $i++) {
        if (isset($array[$matches[$i]])) {
          $repeater_key = $row_key;
          $repeater_value = $row_value;
          $row_key = $field_key;
          $row_value = $field_value;
          $field_key = $matches[$i];
          $field_value = $array[$matches[$i]];
          if ($field_key == $field['key']) {
            break;
          }
          $array = $array[$matches[$i]];
        }
      }
      
      if (!$repeater_key) {
        // this should not happen, but better safe than sorry
        return $valid;
      }
      
      // look for duplicate values in the repeater
      foreach ($repeater_value as $index => $row) {
        if ($index != $row_key && $row[$field_key] == $value) {
          // this is a different row with the same value
          $valid = 'this value is not unique';
          break;
        }
      }
      
      return $valid;
    }
    
  • Great! Is that stuff that I realy need! Tnx a lot! I’ll implement this function in my project and give u a feedback!

  • This reply has been marked as private.
  • Hi, I have used the below code to avoid the duplicate entry on repeater field, But it is not working to me, could you help me to resolve the issue.

    Thanks

    Repeated

    function unique_repeater_sub_field($valid, $value, $field, $input) {
      if (!$valid) {
        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 cur  rent row      
      $array = $_POST['acf'];
      
      $repeater_key = false;
      $repeater_value = false;
      $row_key = false;
      $row_value = false;   
      $field_key = false;
      $field_value = false;
      
      for ($i=0; $i<count($matches); $i++) {
        if (isset($array[$matches[$i]])) {
          $repeater_key = $row_key;
          $repeater_value = $row_value;
          $row_key = $field_key;
          $row_value = $field_value;
          $field_key = $matches[$i];
          $field_value = $array[$matches[$i]];   
          if ($field_key == $field['<strong>field_5731ff201fa2e</strong>']) {
            break;
          }
          $array = $array[$matches[$i]];
        }   
      }
      
      if (!$repeater_key) {
        // this should not happen, but better safe than sorry
        return $valid;
      }
      
      // look for duplicate values in the repeater
      foreach ($repeater_value as $index => $row) {
        if ($index != $row_key && $row[$field_key] == $value) {
          // this is a different row with the same value
          $valid = 'this value is not unique';
          break;
        }
      }
            
      return $valid;
    }
         
    
    add_filter('acf/validate_value/key='.$field_key, 'unique_repeater_sub_field', 20, 4);
  • Hello,

    I have added the below code to avoid the duplicated content, but this is not working to me could you help me to resolve the issue?

    function unique_repeater_sub_field($valid, $value, $field, $input) {
      if (!$valid) {
        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 cur  rent row      
      $array = $_POST['acf'];
      
      $repeater_key = false;
      $repeater_value = false;
      $row_key = false;
      $row_value = false;   
      $field_key = false;
      $field_value = false;
      
      for ($i=0; $i<count($matches); $i++) {
        if (isset($array[$matches[$i]])) {
          $repeater_key = $row_key;
          $repeater_value = $row_value;
          $row_key = $field_key;
          $row_value = $field_value;
          $field_key = $matches[$i];
          $field_value = $array[$matches[$i]];   
          if ($field_key == $field['field_5731ff201fa2e']) {
            break;
          }
          $array = $array[$matches[$i]];
        }   
      }
      
      if (!$repeater_key) {
        // this should not happen, but better safe than sorry
        return $valid;
      }
      
      // look for duplicate values in the repeater
      foreach ($repeater_value as $index => $row) {
        if ($index != $row_key && $row[$field_key] == $value) {
          // this is a different row with the same value
          $valid = 'this value is not unique';
          break;
        }
      }
            
      return $valid;
    }
         
    
    add_filter('acf/validate_value/key='.$field_key, 'unique_repeater_sub_field', 20, 4);

    Repeated

  • 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',
    	]);
    
    }
  • Hello @tomgreeen

    Does this code still work? I have placed them using code snippets but with not effect. The Prevent duplicates radio buttons show in the field groups setting page.

    Thank you.

Viewing 8 posts - 1 through 8 (of 8 total)

You must be logged in to reply to this topic.

We use cookies to offer you a better browsing experience, analyze site traffic and personalize content. Read about how we use cookies and how you can control them in our Cookie Policy. If you continue to use this site, you consent to our use of cookies.