Support

Account

Home Forums Feature Requests Disable Layout from Showing in Template

Solving

Disable Layout from Showing in Template

    • B0yan

    • August 19, 2017 at 1:06 am

    Sometimes I want to hide/remove a Flexible Content layout from showing on the front-end of the website, but would still like to keep it in the back-end in case I want to re-enable that layout again in the future for that page.

    Of course I can always just remove the layout, but if it’s a complex group of fields with a lot of data, recreating it later would be a pain, so in these situations it would be great to have the option to just “disable” the layout.

    For the time being, I’ve created a custom workaround where I create a True / False field with a name of “disable_layout” for every layout, then hide that field with CSS, create a new custom button in the handle of the layout which toggles the True / False field and in my template I only echo my layouts if the field is unchecked.

    Disable ACF Layout

    ACF:

    function acf_admin_footer() {
        ?>
        <script>
        jQuery(document).ready(function($) {
            // Create a custom "disable" button in the layout handles
            $('.acf-fc-layout-controlls').prepend('<a class="acf-icon -disable small light acf-js-tooltip" href="#" title="Disable/Enable Layout"></a>');
    
            // Toggle the hidden checkbox when the custom button is clicked
            $('.acf-icon.-disable').on('click', function() {
                var layout = $(this).closest('.layout');
                layout.toggleClass('disabled-layout');
    
                var checkbox = layout.find('[data-name=disable_layout] input[type=checkbox]');
                checkbox.prop('checked', !checkbox.prop('checked'));
            });
    
            // Check if a layout is disabled when page is loaded
            $('[data-name=disable_layout] input[type=checkbox]:checked').each(function() {
                $(this).closest('.layout').addClass('disabled-layout');
            });
        });
        </script>
    
        <style>
        /* Hide the default ACF checkbox */
        [data-name=disable_layout] {
            display: none;
        }
    
        /* Style the custom layout handle button */
        .acf-icon.-disable:before {
            content: '\e805';
        }
        .disabled-layout .acf-icon.-disable:before {
            content: '\e808';
        }
        .acf-flexible-content .layout .acf-fc-layout-controlls .acf-icon.-disable {
            visibility: hidden;
        }
        .acf-flexible-content .layout:hover .acf-fc-layout-controlls .acf-icon.-disable {
            visibility: visible;
        }
    
        /* Make disabled layout look "disabled" */
        .disabled-layout {
            opacity: 0.4;
        }
        .disabled-layout .acf-fc-layout-handle:after {
            content: ' (Disabled)';
        }
        </style>
        <?
    }
    add_action('acf/input/admin_footer', 'acf_admin_footer');

    Template:

    $disable_layout = get_sub_field('disable_layout');
    
    if (!$disable_layout) {
        // Echo Layout
    }

    I’m not sure how common that situation is for other people, but while my workaround does exactly what I need it to do, I would love to have this as a native feature in the core of ACF as it would be a cleaner implementation. It can possibly even be extended for entire Field Groups that use the Standard (WP metabox) style instead of just for Flexible Content layouts.

  • I have done this for layouts based on a post type, not sure if this will help you at all, and you’d need to work out how to do it for a template

    
    // the key is the field key for the flex field
    // the priority is set exceedingly high to ensure it runs last
    add_filter('acf/load_field/key=field_5808cd92035a5', 'remove_layouts', 99);
    
    function remove_layouts($field) {
      if (!is_admin()) {
        // not on front end
        return $field;
      }
      // this is the part I'm not too sure about
      // you need to check to see if it's where you want to remove the layout
      // then
      if (!$condition) {
        return $field;
      }
      
      // move current layouts into a var
      $layouts = $field['layouts'];
    
      // clear layouts
      $field['lahyouts'] = array();
      
      // list of layouts you don't want to include
      $remove = array('layout_1', 'layout_2', 'etc...');
    
      foreach ($layouts as $layout) {
        // check
        if (!in_array($layout['name'], $remove)) {
          // keep this layout
          $field['layouts'] = $layout;
        }
      } // end foreach
      return $field;
    } // end function
    

    I don’t know if it’s possible, but it may be, to add a custom setting to for flex fields for active and then check all flex fields when loading https://www.advancedcustomfields.com/resources/adding-custom-settings-fields/

    • B0yan

    • August 19, 2017 at 2:41 am

    Thanks for the suggestion John. Using a filter and a custom setting might indeed simplify my solution and save me from manually creating a hidden checkbox field for every layout.

    I’ll have to investigate that approach and see if it’s possible – if anybody has some code to share, that would be great.

    Of course, I would still prefer if that option was eventually natively added to ACF. 🙂

  • I’ve done some checking on this and there is currently no way to add settings to a layout, only to the flex field itself. No filters or actions currently exist in the flex field layout area. So, the method I posted or your method is the only way to do this right now. Although you might also be able to do this on the acf/prepare_field hook, which might be a better choice then on the hook I suggested above.

    • B0yan

    • August 19, 2017 at 4:50 pm

    Thanks for checking this John.

    It’s unfortunate that there are no filters available for targeting the layouts themselves… perhaps that should be another feature request on its own?

    • kayla

    • August 8, 2019 at 9:38 am

    @b0yan – what file did you add your code to in order to enable this setting?

    This is the functionality I need for one of my client’s sites and would love a little more detail about how to incorporate it into the plugin!

    Best,
    Kayla

    • B0yan

    • August 9, 2019 at 2:26 am

    @kayla

    My approach is essentially creating a True/False ACF field in the layout with a name of “disable_layout” and then in the template code of the theme where the ACF layout will be shown performing a simple check if the field is checked or not.

    Theme file (index.php)

    
    // Your True/False Field
    $disable_layout = get_sub_field('disable_layout');
    
    if (!$disable_layout) {
        // If field is unchecked, add your code for the ACF layout field 
    }

    The rest of the code is just aesthetic – to make the field editing on the wp-admin back-end look a little better by moving the disable field in the layout handle and adding a few other tweaks for greying out disabled fields. Since my original post, ACF has changed the classname “acf-fc-layout-controlls” to “acf-fc-layout-controls” – so the code should still work by changing that classname, so the function becomes:

    <?php
    function acf_disable_in_handle() {
        ?>
        <script>
        jQuery(document).ready(function($) {
            // Create a custom "disable" button in the layout handles
            $('.acf-fc-layout-controls').prepend('<a class="acf-icon -disable small light acf-js-tooltip" href="#" title="Disable/Enable Layout"></a>');
    
            // Toggle the hidden checkbox when the custom button is clicked
            $('.acf-icon.-disable').on('click', function() {
                var layout = $(this).closest('.layout');
                layout.toggleClass('disabled-layout');
    
                var checkbox = layout.find('[data-name=disable_layout] input[type=checkbox]');
                checkbox.prop('checked', !checkbox.prop('checked'));
            });
    
            // Check if a layout is disabled when page is loaded
            $('[data-name=disable_layout] input[type=checkbox]:checked').each(function() {
                $(this).closest('.layout').addClass('disabled-layout');
            });
        });
        </script>
    
        <style>
        /* Hide the default ACF checkbox */
        [data-name=disable_layout] {
            display: none;
        }
    
        /* Style the custom layout handle button */
        .acf-icon.-disable:before {
            content: '\e805';
        }
        .disabled-layout .acf-icon.-disable:before {
            content: '\e808';
        }
        .acf-flexible-content .layout .acf-fc-layout-controls .acf-icon.-disable {
            visibility: hidden;
        }
        .acf-flexible-content .layout:hover .acf-fc-layout-controls .acf-icon.-disable {
            visibility: visible;
        }
    
        /* Make disabled layout look "disabled" */
        .disabled-layout {
            opacity: 0.4;
        }
        .disabled-layout .acf-fc-layout-handle:after {
            content: ' (Disabled)';
        }
        </style>
        <?
    }
    add_action('acf/input/admin_footer', 'acf_disable_in_handle');

    You add the above function acf_disable_in_handle() in your theme’s functions.php file or your child theme’s functions.php file. Alternatively, you can even make it into a tiny plug-in, just create a new file in your wp-content/plugins folder – call it disable-acf-layout.php for example and add a comment /* Plugin Name: Disable ACF Layout */ at the top of the file, first thing after the starting <?php

  • I think something changed in the code between 2017 when John’s solution was posted and now (ACF 5.8.5) – I had to edit the foreach loop to make this work without throwing an illegal offset error. Here’s my working code. It looks to see if someone is editing an ‘application’ custom post type – if they are not, it won’t show the ‘integration_logos’ layout.

    add_filter('acf/load_field/key=field_5d9e369133b92', 'remove_layouts', 99);
    function remove_layouts($field) {
    	if (!is_admin()) {
    		// not on front end
    		return $field;
    	}
    
    	// you need to check to see if it's where you want to remove the layout
    	$current_screen = get_current_screen();
    	if ('application' == $current_screen->post_type) {
    		return $field;
    	}
    	
    // move current layouts into a var
    	$layouts = $field['layouts'];
    
    	// clear layouts
    	$field['layouts'] = array();
    	
    	// list of layouts you don't want to include
    	$remove = array('integration_logos');
    
    	foreach ($layouts as $k => $layout) {
    		$name = $layout['name'];
    		// check
    		if (!in_array($name, $remove)) {
    			$field['layouts'][ $layout['name'] ] = $layout;
    		}
    	} // end foreach
    	return $field;
    } // end function
  • Ha, one last tweak – if you still want the layout to show up on the Custom Fields editing screen, add this to the if (!is_admin()… line:

    if (!is_admin() || 'acf-field-group' == $current_screen->post_type) {
      // not on front end and not when editing the Flexible Content field itself
      return $field;
    }
Viewing 9 posts - 1 through 9 (of 9 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.