Home › Forums › Add-ons › Repeater Field › ACF 5.0+ Dynamically Populating Repeater
I’ve been reading a ton of topics regarding populating the repeater field and they all say the same thing: “Use acf/load_Value
hook and return a multidimensional array of values keyed by subfield keys”. Which I have an example of below:
Array
(
[0] => Array
(
[field_5b69f119ce5d2] => Name Here
[field_5b69f1a8ce5d4] => Address Here
)
)
Whenever I run mock tests, the filter hook expects an integer ( number of subfields ) to be returned. Then all the subfields are run through the same acf/load_value
hook but there’s nothing to discern them from regular fields besides the concatenated name. Are the old ways supposed to work in 5.0+? With acf-json
? Open to any tips or suggestions on how I can get his to work.
—
What I’m trying to do is load values from a custom table into the repeater field. Assuming I have an array as seen above, how to I populate the repeater field as such? I’m using acf-json
to store my fields. Here’s the function I’m working with:
add_filter( 'acf/load_value', function populate_custom_table_data( $value, $post_id, $field ) {
if( ! empty ( $value ) && ! empty( $field['custom-attribute-here'] ) ) {
return $value;
}
$table_util = new Custom_Table_Utility();
$value = $table_util->get_data( $post_id, $field['name'] );
$value = ( empty( $value ) && 'true_false' !== $field['type'] ) ? '' : $value;
// Replace reapter field name keys with actual field keys
if( 'repeater' == $field['type'] && ! empty( $value ) ) {
/*
* $value = Array
* (
* [0] => Array
* (
* [database_column_name] => Name Here
* [database_col_address] => Address Here
* )
* )
*/
$subfield_keys = wp_list_pluck( $field['sub_fields'], 'key' );
if( count( $subfield_keys ) == count( $value[0] ) ) {
foreach( $value as $key => $row_values ) {
$value[ $key ] = array_combine( $subfield_keys, $row_values );
}
/*
* $value = Array
* (
* [0] => Array
* (
* [field_5b69f119ce5d2] => Name Here
* [field_5b69f1a8ce5d4] => Address Here
* )
* )
*/
}
}
return $value;
}, 10, 3 );
I’ve also tried to populate it into the sub_fields
index using the acf/load_field
hook to no avail. With the acf/load_field
hook I tried skipping repeater fields entirely and returning the row count but both shows the same results. I think I’m too early at this hook so it’s ignoring the sub_fields
.
The solution is a bit messy and filled with a bunch of my classes functionality that won’t make much sense.
The gist is that:
What I did was check the field type against ‘repeater’ and returned my custom database value count. At the top of the hook I checked if the $field[‘parent’] was empty, if not I used get_field_object( $field['parent'], $post_id, false, false )
to get the parent field name that the subfield are prefixed with.
Once I returned the count to the repeater and stripped the parent name prefix off the subfields I was able to prepopulate the repeater with my custom table data. I have no idea if this will be helpful to anyone but at least it’s no longer a niche issue on the forums here.
Thanks for posting the solution – even returning an integer has moved me forward a bit.
I know you are saying your code is full of red herrings relating to your plugin, could you post some of it anyway? – I can’t workout what to do based on this;
stripped the parent name prefix off the subfields I was able to prepopulate the repeater with my custom table data
Tantalising. Sorry to be a pain asking for the codez !
Robbie
@mcnab It looks like this:
/**
* Load value from custom table
*
* @param Mixed $value
* @param Integer $post_id
* @param Array $field
*
* @return $value
*/
function populate_custom_table_data( $value, $post_id, $field ) {
if( ! empty( $value ) ) {
return $value;
}
$has_parent_field = false;
$field_name = $field['name'];
/**
* Grab parent field and get value by the parent field name
* Use conditional below to populate the actual fields.
*/
if( ! empty( $field['parent'] ) && false !== strpos( $field['parent'], 'field_' ) ) {
// false, false is important to prevent infinite recursive loop.
$parent_field = get_field_object( $field['parent'], $post_id, false, false );
$has_parent_field = ( ! empty( $parent_field ) );
$field_name = ( $has_parent_field ) ? $parent_field['name'] : $field_name;
}
// Grab data from custom table
$db_data = $this->data_util->get_data( $post_id, $field_name );
$value = $db_data;
// Return early if value is empty
if( empty( $value ) ) {
return $value;
}
// We're in a subfield
if( $has_parent_field ) {
$field_concat_name = $field['name'];
$field_concat_name = str_replace( sprintf( '%1$s_', $field_name ), '', $field_concat_name );
preg_match( '(\d{1,})', $field_concat_name, $possible_keys );
if( ! empty( $possible_keys ) ) {
$arr_index = $possible_keys[0];
$field_concat_name = str_replace( sprintf( '%1$d_', $arr_index ), '', $field_concat_name );
// Now we know what index in our subarray
$subfield_arr = $db_data[ $arr_index ];
// Overwrite $value to actual subfield value
// Now that we know the name we can grab it from our named index array
$value = ( ! empty( $subfield_arr[ $field_concat_name ] ) ) ? $subfield_arr[ $field_concat_name ] : '';
}
} else if( 'repeater' == $field['type'] ) { // Return repeater count
$value = count( $db_data );
}
return $value;
}
add_filter( 'acf/load_value', 'populate_custom_table_data', 20, 3 );
@howdy_mcgee – you are an absolute legend.
Thanks a million for coming back with this, it’s a huge help. Will crack on with this and reply to add anything I can to the thread for future users.
Cheers,
Robbie
I was running ACF PRO 5.7.0 but as an mu-plugin so it wasn’t obvious to me there was newer versions.
Elliot replied in a ticket to me;
In the most recent versions of ACF and ACF PRO we have moved around the order of actions allowing the “acf/load_value” action to run last (after “acf/load_value/type=repeater”).
If you hook into the “acf/load_value” filter, you should now be able to customize the repeater field value as an array, not as a numeric number.
So this has changed very recently. Now with version 5.7.6 you can handle it like this;
function my_acf_load_method($value, $post_id, $field) {
if ($field['type'] == 'number') {
$value = 123;
return $value;
} elseif ($field['type'] == 'repeater') {
$value[] = array(
'field_url' => 'http://www.google.com',
'field_text' => 'Google'
);
return $value;
}
}
add_filter('acf/load_value', 'my_acf_load_method', 20, 3);
Checking the value of your repeater, returning $value as a string where the acf/load_value method is expecting a string, and $value as an array when it’s expecting an array.
Much easier, thanks again Howdie_McGee.
The topic ‘ACF 5.0+ Dynamically Populating Repeater’ is closed to new replies.
Welcome to the Advanced Custom Fields community forum.
Browse through ideas, snippets of code, questions and answers between fellow ACF users
Helping others is a great way to earn karma, gain badges and help ACF development!
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.