Home Forums Add-ons Repeater Field Create New Repeater Row from Front End Form


Create New Repeater Row from Front End Form

  • I have done a bit of researching and have not found anything clear. I know that acf_form() can be used but for this I am looking for something different or a way to hook into acf_form().

    I have a custom post type that contains a repeater field with multiple fields including a Google Map field. On the front-end I am using the repeater rows to put pins on a front-end Google Map. I am looking to create a front-end form that would allow someone to fill out a form and hit submit to add a new marker on the map.

    When the person submits a form it will add a new repeater row to the post with the submitted data then show the new marker on the page. If I use acf_form() it shows the entire repeater field. I don’t want anyone on the front to change existing rows all I want is for someone to be be able to fill out a form to create a new row.

    Any ideas or if anyone has a doc or form on this that would be great.

  • Hi Joe,

    Do I understand you correctly if I think you have a larger field group which contains amongst else a repeater field? And the repeater field in term contains multiple fields including a google map field.

    I think the easiest way for you to do this would be to create another field group for your CPT. In it you’ll put just a single google maps field. Then set the field_groups parameter of acf_form() to the new group so that a visitor only see this single google maps field.

    Then you hook into the save_post action. Make the necessary checks to make sure it’s your CPT and a value has been set to the new google maps field.

    Here’s the tricky part. There is no easy way to add a new row programmatically to ACF. There’s only the update_sub_field function which are capable of updating an existing subfield value.

    So what you need to do is first fetch the repeater fields value directly from the DB (which is a number corresponding to how many rows there are). Update it with +1 and then you can use update_sub_field.

    I’ve done this myself in a project recently and it works 🙂

    Here’s some sample code for how to create a new row and add values to it from within functions.php

    //Our single google maps field
    $temp_map = get_field('field_name');
    //Repeater field
    $repeater = get_post_meta($post_id, 'field_name', true);
    //If there are no rows yet just set to 1, otherwise +1
    $new_repeater_count = ( !$repeater ? 1 : $repeater + 1 );
    update_post_meta($post_id, 'field_name', $new_repeater_count);
    //Now we can start adding our sub field values. However the update_sub_field function takes 0 as base so we actually need to subtract 1 from our $new_repeater_count
    $index = $new_repeater_count -1;
    //Update the map sun field
    update_sub_field( array( 'repeaterfieldkey', $index, 'subfieldkey' ), $temp_map), $post_id );
    //And now we want to clear the single google maps field since there shouldn't be any preset address for the next person!
    update_field('fieldkey', '', $post_id);

    Let me know how that works out!

  • Hi @jonathan I really appreciate the input. You solution/work around makes sense but I am a little concerned because I feel like I may be putting a bandaid on the submit to repeater since it’s not truly supported.

    I may handle this a little different than I originally planned since there are going to be 1000s of posts each with up to 20 repeater rows per-post. I think I may create a post type to store the actual location data (what I am calling sightings). I can then create a relationship between the listings post type and the sightings post type. I should be able to then query everything as needed. Thanks for the help.

  • Hi @joesilva7765

    Alright that’s another way to go 🙂
    For me it was just 8 rows in each post (thousands of posts tho). It works like a charm but would of course break if elliot ever decides to change the actual DB value of the repeater field. I’ll save that for a rainy day.

  • Hello old thread!

    FYI, this is now easier using the update_row function

    instead of:
    update_sub_field( array( ‘repeaterfieldkey’, $index, ‘subfieldkey’ ), $temp_map), $post_id );
    Do this:

    $row = array(
    				'repeater_child_fieldname'	=> $temp_map,
    				'repeater_child_fieldname2'	=> etc....,
    			update_row( 'repeater_name_or_key', $index, $row, $post_id );
  • Hi Jonathan,

    I think there is an update/change to the code that make the minus 1 to $new_repeater_count unnecessary.

    looking in .//advanced-custom-fields-pro/api/api-template.php for ACF Pro v 5.4.2 – on line 1607 there is this.

    			if( is_numeric($s) ) {
    				// get row index
    				$row_i = intval($s) - 1;
    				// add to name
    				$name .= "_{$row_i}";
    			} else {

    So it seems like the -1 is now built in the code.

    I’m not too thrilled with this, as now I have to remember yet another hidden functionality to the update_sub_field() function.

    I would update Jonathan’s code to something like this.

    $repeater = get_post_meta($orgPost, 'org_users', true);
    $index = (!$repeater) ? 1 : $repeater + 1;
    update_field(ORG_USERS_FIELD_KEY, $index, $orgPost);
    update_sub_field(array(ORG_USERS_FIELD_KEY, $index, ORG_USER_SUB_FIELD_KEY), $user_id, $orgPost);
  • I believe you’re right, because I’m using the below code and not having to do any weird math like that.

    //Add a row with the user's info as an admin to the Staff repeater field
    			//There are no rows yet, so we update the value of the repeater field to 1 to make a new row
    			//The value of the repeater field is simply a number representing the number of existing row
    			//If ACF ever changes the value of the repeater field in the database, this will need adjusting
    			if (get_post_meta($post_id, 'choose_tps_members')) {
    				$existingRows = get_post_meta($post_id, 'choose_tps_members', true);
    				if (have_rows('choose_tps_members', $post_id)) {
    						$selectedMembers = array();
    					while(have_rows('choose_tps_members', $post_id)) {
    						$selectedMembers[] = get_sub_field('choose_member'); //user array
    			//Add a row to the repeater
    			update_post_meta($post_id, 'choose_tps_members', $existingRows+1);
    			//Update repeater row we just created with the Creator's info
    			$setUser = get_user_by('id',$creator);
    			$row = array(
    				'choose_member'	=> $setUser, //Creator
    				'make_admin'	=> array('Admin'), //Check the "make admin" box
    			//Update the repeater row
    			update_row( 'choose_tps_members', $existingRows+1, $row, $post_id );
    			//Once all fields validate, we can finally publish it
    			wp_update_post(array('ID'=>$post_id, 'post_status'=>'publish'));
  • arcanipsyche –

    aren’t these three lines doing the same thing?

    $repeater = get_post_meta($post_id, 'choose_tps_members', true);
    if (get_post_meta($post_id, 'choose_tps_members')) {
       $existingRows = get_post_meta($post_id, 'choose_tps_members', true);
  • Yes, that first line looks like a leftover from a previous attempt or something. It can be remove and everything works the same. I’ve done so. Good eye.

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

You must be logged in to reply to this topic.