Support

Account

Home Forums Add-ons Repeater Field dynamically generate subfield content

Solved

dynamically generate subfield content

  • I have a repeater field with a text field subfield.

    I would like to dynamically generate mulitple text subffields that each have a different default value.

    Basically I have a options page with a repeater on it. This repeater has a text subfield. The site admin can specify zero or more default values on the options page. When the fields for a new post are shown I’d like to be able to populate as many text subfields as there are on the options page with the values from the options page.

    Is this possible?

    I’ve been looking through testing the load_field and load_value filter hooks, but can’t seem to figure this one out. Could be it’s not possible, but thought I’d ask just in case I’m missing something.

    If it’s not possible I can look for a different solution instead.

    Thanks

  • Hi @hube2

    The filter to use is the acf/load_value filter.
    You would use this to hook in and modify the repeater field’s value that appears on a ‘post’ (not options page).

    In this filter, you can load the options page value and write some logic to loop over the options page value and append any necessary data to the real $value.

    Thanks
    E

  • I’ve tried using acf/load_value, but I’m missing something when it comes to the subfields of a repeater. Heh, I’ve figured out how to populate default content in in almost every other type of field but this one has me stumped for some reason 😛

    Do I add the filter for the repeater field or each of the subfields?

  • I’m guessing that my problem was/is that there are no subfields to begin with in what I was trying.

    I just did this on another repeater that has a minimum number of subfields that must be set and it works fine.

    So what I guess I really need to figure out is how to dynamically create some arbitrary number of subfield rows when a new post is being created.

  • Just in case anyone else needs this information.

    So, to create an arbitrary number of subfields for a new post, if I have a repeater named “bf_test_repeater”

    
    add_filter('acf/load_value/name=bf_test_repeater',  'afc_load_bf_test_repeater_value', 10, 3);
    function afc_load_bf_test_repeater_value($value, $post_id, $field) {
      if ($value === false) {
        // this is a new post since value === false
        // set value to number of default # of rows to create
        $value = 5;
      }
      return $value;
    } 
    

    I’ll have more code than this since it will need to figure out by looking at the options page how many rows to start with. Then I’ll need the code for each of the sub-fields to set the value to the next value retrieved from the options page.

  • Please can you explain how you did this in the end? I need to do pretty much exactly what you’ve described. A repeater in the options page populating repeater in an acf field group on a post page when it’s created… I thought of using acf/load_field and update_field() to change the value but don’t know how to do this with a repeater. Please help.

  • I’m building a plugin, so I’m building everything into a PHP class. I say this because you need to create some counters to keep track of where you are. If you’re not using classes then you’ll need to use global variables to do the counters.

    Here are the steps.

    During initialization I read in the values from the repeaters and store them into an array. The array will need to be either a class property or global variable. this function should probably run at “plugins_loaded” to make sure that ACF functions are available for retrieving your repeater field data.

    the next step is to set the correct number of repeats. That’s done with the function I gave in my last comment. You just need to return the count of the array that holds your subfield data.

    For each subfield you need to create a another filter, along with a counter to keep track of where you need to be.

    
    global $subfield_1_counter;
    $subfield_1_counter = 0;
    add_filter('acf/load_value/name=subfield_1',  'afc_load_dubfield_1_value', 10, 3);
    function afc_load_dubfield_1_value($value, $post_id, $field) {
      global $subfield_1_counter;
      // code to calculate next value for this field
      // the exact code here will depend on the type of field being initialized
      // after setting the value, increment the counter and return the value
      $subfield_1_counter++;
      return $value;
    }
    

    To be honest, I don’t have exact details on what I did because I haven’t completed this part yet. Like I said, I’m doing this for a plugin that I’m building and my attention has been diverted from that project. This is how I plan to proceed when my workload drops enough so I can return to it.

    Hope this helps.

  • I’m able to set the value of the repeater so that the number of subfields matches the number of subfields in my options repeater.
    But I still don’t understand how you would go about setting the values of the subfields from there. If I try to access the subfields I only get the structure and not the content. So even if I wanted to create another filter for each subfield I wouldn’t know the field_key to do so.

    function repeater_field_load_value($value, $post_id, $field) {
    		
        $keywords = get_field('app_store_metadata_keywords', 'option', true);
        $num_of_keywords = sizeof( $keywords );
    	
        if ( $value != $num_of_keywords ) {
            $value = $num_of_keywords;
        }
        
        // This doesn't show any value for the subfields ?
        echo '<pre>';
        print_r( $field['sub_fields'] );
        echo'</pre>';
    	
        return $value;
    }
    
    add_filter($'acf/load_value/name='my_field_name', 'repeater_field_load_value', 10, 3);
  • When you create a subfield of a repeater it’s given the name and key just like the parent field is given. so you create the filter for that field name or key.

    http://www.advancedcustomfields.com/resources/filters/acfload_value/

    For example, when I do this my setup will have 3 filters, on for the repeater and 1 for each of the 2 sub-fields in that repeater. The first filter will set a number of default rows for the repeater based on the number of rows in options. The other two will set the values for each row. The only thing I left out of my description above is that I only want to set the value if the first filter actually set the number of rows. So my first function would actually look something like:

    
    add_filter('acf/load_value/name=my_repeater',  'afc_load_my_repeater_value', 10, 3);
    function afc_load_my_repeater_value($value, $post_id, $field) {
      if ($value === false) {
        // this is a new post since value === false
        // set value to number of default # of rows to create
        // based on number of rows created on options page
        $value = 5;
        // add filters to call subfield filters here
        // they are only created if we're supposed to use the default values
        add_filter('acf/load_value/name=sub_field_1',  'afc_load_sub_field_1_value', 10);
        add_filter('acf/load_value/name=sub_field_2',  'afc_load_sub_field_2_value', 10);
      }
      return $value;
    }
    function afc_load_sub_field_1_value($value) {
      // get next value for subfield 1 and return
      return $value
    }
    afc_load_sub_field_2_value($value) {
      // get next value for subfield 2 and return
      return $value
    }
    

    the actual subfield filters would be a bit more complicated because the values from the options page would need to be stored in an array in a global variable so that it can be accessed by my function and then each function would need to step through the values to return the next value for each subfield.

    Like I said, I have not actually gotten to building the part where the subfields are set to the options page value. I just know what I’ll need to do when I get back to it and will test and figure out the details then.

    Sorry, that’s about the best I’m going to be able to do as far as an explanation right now.

  • This has been bugging me for quite a while, but I think I’ve finally cracked it. It was almost disappointingly simple in the end – $value needs to be an array.

    
    add_filter('acf/load_value/key=field_54aa5b3b008b0',  'afc_load_my_repeater_value', 10, 3);
    function afc_load_my_repeater_value($value, $post_id, $field) {
    	if ($post_id === false) {
    		$value	= array();
    		$value[] = array(
    			field_54aa5beb008b1 => 'Hours',
    			field_54aa5c25008b2 => 1
    		);
    		$value[] = array(
    			field_54aa5beb008b1 => 'Minutes'
    		);
    		$value[] = array(
    			field_54aa5beb008b1 => 'Seconds'
    		);
    	}
    	return $value;
    }
    

    This case is pretty straight forward; I have one repeater field field_54aa5b3b008b0 that has two text fields inside it (field_54aa5beb008b1 and field_54aa5c25008b2). I imagine the same setup will apply to more in-depth scenarios as well with some tweaking.

    Step 1. Hook into acf/load_value on your repeater field. You can use type/key/name as desired here.

    Step 2. Check if the $post_id is set or not. If you want to modify the values of existing posts as well you wouldn’t need to, but here I want to set default values for new posts only.

    Step 3. Set $value to your array of default values. Above, I have 3 rows by default on new posts. Each row has two values – ‘unit of time’ and ‘amount of time’. The ‘unit of time’ values are set to “Hours”, “Minutes” and “Seconds”. The ‘amount of time’ value on the “Hours” row I have set default to 1. In the other rows, I didn’t want the second value to be set by default, so it’s omitted – if omitted, ACF uses the default value set in the admin (or just blank).

    Step 4. Return the $value. Make sure you always return it – even if you haven’t modified it.

    ———– NOTES
    – I’m using ACF Pro 5.1.8, but it should work in other versions as well (using the proper hooks as needed).
    – The sub fields appear to be required to the the exact field key – field name and type haven’t worked for me.
    – Above, I’m setting a static set of values as my defaults. You could certainly call a function or otherwise dynamically load an array into $value from elsewhere as well – just need to make sure it uses the key for sub fields.
    – If you’re not sure how the array should be set up, just print out an array from an existing repeater in the wp-admin like this:

    
    add_filter('acf/load_value/key=field_54aa5b3b008b0',  'afc_load_my_repeater_value', 10, 3);
    function afc_load_my_repeater_value($value, $post_id, $field) {
    	echo print_r($value);
    	return $value;
    }
    

    This will print out the repeater value from an existing post. Save the post with some rows in your repeater and you’ll see a guide of how to set up the array of defaults.

  • To anyone reading this now, DACrosby’s answer still works except you have to wrap the array keys within the $value[] array with quotes (e.g. ‘field_54aa5beb008b1’ )

    
    add_filter('acf/load_value/key=field_54aa5b3b008b0',  'afc_load_my_repeater_value', 10, 3);
    function afc_load_my_repeater_value($value, $post_id, $field) {
    	if ($post_id === false) {
    		$value	= array();
    		$value[] = array(
     
    			'field_54aa5beb008b1'/* Correct */ => 'Hours',
    			field_54aa5c25008b2 /* Incorrect */ => 1
    		);
    	}
    	return $value;
    }
    
Viewing 11 posts - 1 through 11 (of 11 total)

The topic ‘dynamically generate subfield content’ is closed to new replies.