Support

Account

Home Forums ACF PRO How to add custom class to admin_body_class based on ACF field data?

Solved

How to add custom class to admin_body_class based on ACF field data?

  • Hey guys,
    I am struggling to implement one small thing but unfortunately, there is not much quality search result available for using admin_body_class hook with ACF data.

    Now we can easily add custom CSS classes to the body_class filter which adds the custom class on the front end of the website. It’s super easy to do with something like this:

    add_filter( 'body_class', function( array $classes ) : array {
      if( get_field( 'some_field' ) ) {
    		$classes = array_merge( $classes, [ 'some-class' ] );
    	}
    
      return $classes;
    } );

    But when it comes to using the admin_body_class a ton of issues appears. For example, the get_field() will not work inside that filter as that is running on the admin side. So, I am trying to understand how this can be achieved.

    What I am looking to do is basically on the back end I have a dropdown menu asking users which kind of page container do they want. A full width one or a narrow width one.

    Now what I want to do is based on the option they select I want to add a custom class to the admin_body_class so that then using CSS I can set the Gutenberg container width to the same as it will on the front end so that it looks as similar as possible.

    Does anyone have an idea on how to achieve that? Thanks in advance and your helps are greatly appriciated.

  • You are correct that get_field() will not automatically work because you are on the admin side, however, it is possible to pass the post_id you want the value from as a parameter:

    global $post;
    get_field('some_field', $post->id);

    There is however still an issue with that global post. Especially on post creation this might not work properly and another issue is that you could only see results by saving your changes and then refreshing the page.

    My advice is to load some custom javascript in the admin and add/change/remove classes on the admin body using jQuery (or just vanilla).

  • My advice is to load some custom javascript in the admin and add/change/remove classes on the admin body using jQuery (or just vanilla).

    – I was planning to write some vanilla js but did not find an easy way to fetch the ACF field data inside the JS. If you have an example JS snippet of how it can be done that would really help.

  • You are attempting to access to value of the field outside of “The Loop”. This means that ACF will not know what post to get the value from and you must supply that.

    
    $queried_object = get_queried_object();
    if (is_a($queried_object, 'WP_Post')) {
      $value = get_field('field_name', $queried_object->ID);
    }
    
  • Hi,
    First of all thanks a ton to Jelmertje & John for all the help and guidance. Anyways. I have finally done it and here I am sharing the solution in the hope it might help others someday in future.

    So, if you are trying to add a custom class to the admin body based on your ACF field data you basically have 2 ways to do that.
    1. Implement it via PHP admin_body_class and in doing so it will work perfectly but as the user makes the changes in the ACF fields the classes won’t be immediately be added to the admin body class and instead the user needs to refresh the page after changing the ACF field data and saving the post/page.
    2. Implement it via JavaScript so that the classes get added immediately as the user make changes to the ACF fields on the admin end.

    Now here I am going to show both the option so that you can decide which one to use.

    Note:
    – Here I am running 2 checks. One is based on Radio Field data and the other is based on the True/False ACF checkbox field data.
    – The PHP script written below is based on PHP 8 syntax
    – The JS script is based on ES6

    THE PHP WAY
    You can do something like these to add custom classes to your admin body based on ACF field data:

    add_filter( 'admin_body_class', function( string $classes ) : string {
      global $post;
    
      // get_current_screen() returns object with current admin screen
      // @link https://codex.wordpress.org/Function_Reference/get_current_screen
      $current_screen = get_current_screen();
    
      if( $current_screen?->base === 'post' ) {
        // Get the RADIO button type data
        $some_acf_field = get_field( 'some_acf_field', $post?->ID ) ?? false;
        
        // Run the received data through the switch statement
        switch( $some_acf_field ) {
          case 'something' :
            $classes .= ' page-has-something';
          break;
    
          case 'foo' :
            $classes .= ' page-has-foo';
          break;
    
          default :
            $classes .= ' page-has-bar';
          break;
        }
    
        // Check based on ACF True/False checkbox field
        if( get_field( 'true_false_ace_field', $post?->ID ) ?? false ) {
    			$classes .= ' has-some-class';
    		}
      }
    
      return $classes;
    } );

    THE JAVASCRIPT WAY
    Now let’s see how to achieve the same using JavaScript.

    Note:
    – Let’s imaging the file name is editor-logic.js and the file has been added to the admin end with the enqueue_block_editor_assets action.

    Now let’s see what’s inside the file.

    /** 
     * Add/Remove Class from the Admin Body tag based on ACF field Data
     * 
     * ACF Fields Being Monitored:
     * 1. Some Radio Field (Name: some_radio_field) [Key: field_61d716c8459d9]
     * 2. Some True False Field (Name some_true_false_field) [Key: field_61d69ffed41ad]
     */
    
    const add_admin_body_class = ( classType = 'something', value  ) => {
    	const adminBodyClassList = document.body.classList
    
    	if( classType === 'something' ) {
    
    		switch( value ) {
    			case 'foo' :
    				if( adminBodyClassList.contains('page-has-bar') ) {
    					adminBodyClassList.remove('page-has-bar')
    				}
    
    				if( adminBodyClassList.contains('page-has-zar') ) {
    					adminBodyClassList.remove('page-has-zar')
    				}
    
    				adminBodyClassList.add('page-has-foo')
    			break;
    
    			case 'bar' :
    				if( adminBodyClassList.contains('page-has-foo') ) {
    					adminBodyClassList.remove('page-has-foo')
    				}
    
    				if( adminBodyClassList.contains('page-has-zar') ) {
    					adminBodyClassList.remove('page-has-zar')
    				}
    
    				adminBodyClassList.add('page-has-foo')
    			break;
    		}
    	}
    
    	// Add Default Page Title Center Alignment Based Classes
    	if( classType === 'another_thing' ) {
    
    		if( value ) {
    			adminBodyClassList.add('page-has-another-thing')
    		} else {
    			adminBodyClassList.remove('page-has-another-thing')
    		}
    	}
    }
    
    ( () => {
    	// Get the Page Container Type
    	const something = acf.getField('field_61d716c8459d9').val() ?? false
    	const anotherThing = acf.getField('field_61d69ffed41ad').val() ?? false
    
    	// Add the admin body classes based on the initial ACF field values
    	add_admin_body_class( 'something', something )
    	add_admin_body_class( 'another_thing', anotherThing )
    
    	// Listen for changes to the something ACF field values
    	const somethingACFField = document.querySelectorAll( '[data-key="field_61d716c3359d9"] input[type="radio"]' )
    	if( somethingACFField.length > 0 ) {
    		somethingACFField.forEach( ( field ) => {
    			field.addEventListener('change', ( e ) => {
    				add_admin_body_class( 'something', e.target.value )
    			} )
    		} )
    	}
    
    	// Listen for changes to the anotherThing ACF field values
    	const anotherThingACFField = document.querySelectorAll( '[data-key="field_61d69ffed41ad"] input[type="checkbox"]' )
    	if( anotherThingACFField.length > 0 ) {
    		anotherThingACFField.forEach( ( field ) => {
    			field.addEventListener('change', ( e ) => {
    				add_admin_body_class( 'another_thing', e.target.checked )
    			} )
    		} )
    	}
    } )();

    Hope this helps others.

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

You must be logged in to reply to this topic.