Support

Account

Forum Replies Created

  • I had a similar issue where i needed to add the ACF fields meta_id. Below is my solution to the same problem

    function build_meta_key($field){
        // Loop over parents.
        $return_name = $field["_name"];
    
        if(empty($field["prefix"])){
            return $return_name;
        }
    
        $is_row = preg_match("/row-(\d)+/", $field["prefix"], $matches);
    
        if(!$is_row){
            return $return_name;
        }
    
        //now figure out the row number from the field name
    
        $return_name = $matches[1]."_".$return_name;
        
        while ( $field['parent'] && $field = acf_get_field( $field['parent'] ) ) {
            if(isset($field["_name"])){
                $return_name = $field["_name"]."_".$return_name;
            }
        }
    
        return $return_name;
    }
    
    function get_all_meta_info_by_key($post_id,  $meta_key, $meta_type = "post"){
    	global $wpdb;
    	if ( ! $meta_type || ! $post_id || trim($meta_key) == "") {
    		return false;
    	}
    
    	$table = _get_meta_table( $meta_type );
    	if ( ! $table ) {
    		return false;
    	}
    
    	$meta = $wpdb->get_row( $wpdb->prepare("SELECT * FROM {$table} WHERE post_id = %d AND meta_key = %s", $post_id, $meta_key) );
    
    	if ( empty( $meta ) ) {
    		return false;
    	}
    
    	if ( isset( $meta->meta_value ) ) {
    		$meta->meta_value = maybe_unserialize( $meta->meta_value );
    	}
    
    	return $meta;
    }
    
    /**
     * Add in the ACF fields meta id to the field itself. so we can build the download links
     * @param $field
     *
     * @return mixed
     */
    function prepare_field( $field ) {
        global $post;
    
        $acf_meta_key = $this->build_meta_key($field);
    
        $meta_information = $this->get_all_meta_info_by_key($post->ID,  $acf_meta_key);
    
        if(!empty($meta_information->meta_id)){
            $field["post_meta_id"] = $meta_information->meta_id;
        }
    
        return $field;
    }
  • Think i have found a way to achieve what i need.

    I ended up using the pre_load_value filter. which if you hook into and return a value. is then skipped when the repeater field goes to load its value.

    This way i can mimic the load_value function and the acf_get_value function just returns my value as opposed to the system value.

    incase anyone ever needs this in the future here is the code i used.

    add_filter('acf/pre_load_value',   array($this, 'pre_load_value'), 3, 3);
    function pre_load_value( $value, $post_id, $field  ){
    
        if($field['type'] != 'repeater'){
            return $value;
        }
    
        if(!$this->search_sub_fields_for_type($field['sub_fields'], $this->name)){
            return $value;
        }
    
        // Get field name.
        $field_name = $field['name'];
    
        // Check store.
        $store = acf_get_store( 'values' );
        if( $store->has( "$post_id:$field_name" ) ) {
            return $store->get( "$post_id:$field_name" );
        }
    
        // Load value from database.
        $value = acf_get_metadata( $post_id, $field_name );
    
        // Use field's default_value if no meta was found.
        if( $value === null && isset($field['default_value']) ) {
            $value = $field['default_value'];
        }
        //User our own load_value filter to add additional information to subfields
        $value = apply_filters( "ttc_repeater_load_value", $value, $post_id, $field );
    
        // Update store.
        $store->set( "$post_id:$field_name", $value );
    
        // Return value.
        return $value;
    
    }
    
    add_filter('ttc_repeater_load_value',   array($this, 'try_add_grid_info'), 2, 3);
    function try_add_grid_info($value, $post_id, $field){
    
        // bail early if no sub fields
        if( empty($field['sub_fields']) ) return $value;
    
        // vars
        $value = intval($value);
        $rows = array();
    
        $field["total_rows"] = $value;
    
        // loop
        for( $i = 0; $i < $value; $i++ ) {
    
            // create empty array
            $rows[ $i ] = array();
    
            // loop through sub fields
            foreach( array_keys($field['sub_fields']) as $j ) {
    
                // get sub field
                $sub_field = $field['sub_fields'][ $j ];
    
                // bail ealry if no name (tab)
                if( acf_is_empty($sub_field['name']) ) continue;
    
                // update $sub_field name
                $sub_field['name'] = "{$field['name']}_{$i}_{$sub_field['name']}";
                $sub_field["original_order"] = $i;
                $sub_field["latest_row"] = (($field["total_rows"]-1) == $i);
                $sub_field["total_row_count"] = ($field["total_rows"]);
    
                // get value
                $sub_value = acf_get_value( $post_id, $sub_field );
    
                // add value
                $rows[ $i ][ $sub_field['key'] ] = $sub_value;
    
            }
    
        }
    
        return $rows;
    
    }
    
    /** function to loop through sub fields and look for a particular sub field type.
     * @param $sub_fields array of repeater sub fields
     * @param $field_type - Field type we are looking for
     * @return bool
     */
    function search_sub_fields_for_type($sub_fields, $field_type){
        if(!empty($sub_fields)){
    
            foreach($sub_fields as $sub_field){
    
                if(!empty($sub_field["type"]) && $sub_field["type"] == $field_type ){
                    return $sub_field;
                }
            }
    
        }
    
        return false;
    }
  • Hi John,

    Thanks for the response. What i need is to be able to add some variables to the sub field (specifically the repeater’s total rows and the sub field’s row count) before it is rendered.

    I need the value passed the field before the sub field runs it’s load_value function. As I’m using these values to do a seperate DB query for additional information.

    If i set the priority > 10 the sub field has already run through its load_value function and i would have to loop through everything a second time. Which will be fine if i only had a few rows. But i am anticipating over time there will be quite a few rows and i think this will impact in load times.

  • in a javascript file you can add this code to run when a row is added to the repeater field

    (function( $ ) {

    $(".acf-input .acf-repeater").on('click a[data-event="add-row"]', function(evt, el){
        console.log(evt);
    });
    
    })( jQuery );
Viewing 4 posts - 1 through 4 (of 4 total)