Support

Account

Home Forums Bug Reports Formatting being ignored for default field values.

Helping

Formatting being ignored for default field values.

  • Basically my issue is that the get_field() function doesn’t format the default value if meta doesn’t exist for the post…

    1. So I have a select field with choices that are loaded dynamically using the acf/load_field filter.
    2. I then set a default value for the same field using acf/load_value.
    3. And finally, I format the values using acf/format_value.

    For example, I have a field named my_field:

    1. Loading values.

    
    add_filter( 'acf/load_field/name=my_field', function( $field ) {
    
        // Get category terms, for this post
        $terms = get_the_terms( get_the_ID(), 'categories' );
    
        if ( !empty( $terms ) && !is_wp_error( $terms ) ) {
    
            // Reset choices array
            $field[ 'choices' ] = [];
    
            // Enable field
            $field[ 'disabled' ] = false;
    
            // Add terms to choices array
            foreach ( $terms as $category ) {
                $field[ 'choices' ][ $category->term_id ] = $category->name;
            }
        }
    
        // Disable field if no choices
        if ( empty( $field[ 'choices' ] ) ) {
    
            // Set "placeholder" text
            $field[ 'choices' ] = [ 'This post has no categories' ];
    
            // Disable field
            $field[ 'disabled' ] = true;
        }
    
        return $field;
    
    }, 10, 1 );
    

    2. Setting default.

    
    add_filter( 'acf/load_value/name=my_field', function( $value, $post_id, $field ) {
    
        $terms = get_the_terms( $post_id, 'categories' );
        $term_ids = [];
    
        if ( !empty( $terms ) && !is_wp_error( $terms ) ) {
            $term_ids = array_map( function( $term ) {
                return $term->term_id;
            }, $terms );
        }
    
        // Value does not exists
        if ( !in_array( $value, $term_ids ) && !empty( $term_ids ) ) {
    
            // Get the last term in array and set as default
            if ( $last_term = end( $term_ids ) ) {
                return $last_term;
            }
        }
    
        return $value
    
    }, 10, 1 );
    

    3. Formatting value.

    
    add_filter( 'acf/format_value/name=my_field', function( $value, $post_id, $field ) {
    
        if ( !empty( $value ) ) {
            if ( $term = get_term_by( 'id', $value, 'categories' ) ) {
                return $term->name;
            }
        }
    
        return null;
    
    }, 10, 1 );
    

    Now what this does is..
    1. Fill my select field with the saved category terms of the current post with the term_id as the value and the term name as the label.
    2. Then it validates the field value. If it doesn’t match a category term I set the default value to the last category in the get_the_terms array.
    3. Format the value to return the category name not the term_id.

    Now we have default values for this field for all existing posts. But when using the get_field or the_field function we do not get the formatted value which we expect the be the term name. We actually get the term_id.

    Looking at the get_field function in source (includes/api/api-template.php).

    
    function get_field( $selector, $post_id = false, $format_value = true ) {
        
        // filter post_id
        $post_id = acf_get_valid_post_id( $post_id );
        
        
        // get field
        $field = acf_maybe_get_field( $selector, $post_id );
        
        
        // create dummy field
        if( !$field ) {
            
            $field = acf_get_valid_field(array(
                'name'  => $selector,
                'key'   => '',
                'type'  => '',
            ));
            
            
            // prevent formatting
            $format_value = false;
            
        }
        
        
        // get value for field
        $value = acf_get_value( $post_id, $field );
        
        
        // format value
        if( $format_value ) {
            
            // get value for field
            $value = acf_format_value( $value, $post_id, $field );
            
        }
        
        
        // return
        return $value;
         
    }
    

    You can see the function acf_maybe_get_field is called, this tries to find the field based on meta values but we don’t have meta values yet so this returns false. And now because this returns false we fall into the // create dummy field if statement. In here we can see that the function is forcing formatting to be ignored $format_value = false;. We have no way of bypassing this.

    TL;DR
    get_field() ignores formatting for default values. Can this be removed or a workaround added?

    Hope this all makes sense.

  • The reason this happens and why formatting is suppressed is because ACF will not be able to know how to format the value, or event that the field has a default value. acf_maybe_get_field() is looking for at valid field in order to get the field key. If you look into `acf_get_value()’ you’ll find that it’s using the field key to get the value.

    If you have a field and you know that that field will not have any values saved because of things like added the field after the posts were created by using the field key to get the value rather than the field name you will get the default value and it will be formatted. The same issue exists when getting values that have never been set as is described when updating values that have never existed using update_field() https://www.advancedcustomfields.com/resources/update_field/

Viewing 2 posts - 1 through 2 (of 2 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.