Support

Account

Home Forums Feature Requests Filter for flexible content layouts

Solving

Filter for flexible content layouts

    • Noma

    • February 11, 2018 at 5:05 am

    Would it be possible to add a filter for the flexible content layouts that would allow removing some layouts from some templates?

    We have a use case where we do have a same flexible content field in almost all templates of the site, but would like to remove some layouts from some of the templates.

  • There is nothing in ACF that can do this and you have to build something yourself. This would be the equivalent of having location rules for every field.

    I had the same need a few months ago, in my case I needed to show a layout only on a specific post type.

    I created an acf/load_field filter https://www.advancedcustomfields.com/resources/acf-load_field/ for the flex field. I then checked the post type of the post. Then I looped through the layouts in the field settings and removed the ones I didn’t want to show.

    The best I can offer you is the code I used to remove the layouts I did not want to show on other post types

    
    // this is an excerpt from my load field filter
    // above here I decided if the layouts should be shown
    // if not then this code would run
    
    $layouts = $field['layouts'];
    $field['layouts'] = array();
    foreach ($layouts as $layout) {
      if ($layout['name'] != 'product_panel' && $layout['name'] != 'product_specs_panel') {
        $field['layouts'][] = $layout;
      }
    }
    return $field;
    
    • Noma

    • February 20, 2018 at 10:07 pm

    I actually managed to do it for both different post types and different page templates. You can see my solution, if you’re interested: https://github.com/devgeniem/acf-codifier/blob/master/src/Field/FlexibleContent.php#L286.

    Thank you for the help!

  • hello,
    see this i got this from github
    Filter: fcb_bg_colors
    Change or add to the available “theme” background colors for blocks

    add_filter( ‘fcb_bg_colors’, ‘custom_bg_colors’);
    function custom_bg_colors($array) {
    $array[‘secondary’] = ‘Secondary’;
    return $array;
    }
    Filter: fcb_btn_colors
    Change or add to the available button colors for block calls to action

    add_filter( ‘fcb_btn_colors’, ‘custom_btn_colors’);
    function custom_btn_colors($array) {
    $array[‘secondary’] = ‘Secondary’;
    return $array;
    }
    Filter: fcb_set_block_htag
    Set the tag that block titles are wrapped in. This defaults to <h2>. First remove the existing filter and then add your own:

    /**
    * Make the first block title an h1 and subsequent blocks default to h2
    */
    remove_filter( ‘fcb_set_block_htag’, ‘block_htag_level’, 10 );
    add_filter( ‘fcb_set_block_htag’, ‘custom_htag_level’, 10, 2 );
    function custom_htag_level($title, $htag) {
    if($GLOBALS[‘fcb_rows_count’] == 0) {
    $htag = ‘h1’;
    } else {
    $htag = ‘h2’;
    }
    return ‘<‘ . $htag . ‘>’ . $title . ‘</’ . $htag . ‘>’;
    }

  • $landing_page_templates = array(
    array (
    array (
    ‘param’ => ‘post_type’,
    ‘operator’ => ‘==’,
    ‘value’ => ‘page’,
    ),
    array (
    ‘param’ => ‘page_template’,
    ‘operator’ => ‘!=’,
    ‘value’ => ‘template-no-header-image.php’,
    ),
    ),
    );
    add_theme_support( ‘flexible-content-location’, $landing_page_templates );
    for futher steps visit this link.
    see if that works and report.
    <hr>
    BlokadaBobby MovieTvTap

  • NOTE: This plugin is very much a work in progress. It includes a small number of layouts now, and will include more as time allows.

    A WordPress plugin that provides a collection of useful, reusable flexible content blocks for use with ACF Pro 5. Basic templates included and automatically loaded, can be optionally overridden at the theme level.

    This plugin creates a Flexible Content Field below the content editor on Pages and automatically includes content entered there below the_content() on page templates.

    Also wraps the_content() in some basic HTML to make it easy to differentiate from the added content blocks.
    Thanks & Regards,
    Balakrishna yealink voip phone setup

  • We tried lots of solutions here/there/anywhere and they didn’t work for us, we have a series of complex flex content fields and lots of custom post-types, not all layouts need to be used in all post types. We come out with this, maybe help someone:

    The basic idea is to hide the layout from the acf popup.
    This hides 3 layouts from the ACF Popup when you click ADD ROW in POSTS.

    
    function acf_flex_layouts_filter() {
    $type = get_post_type();
    if ($type=="post"): 
    ?>	
    <style>
       .acf-fc-popup a[data-layout='layout_name_1'] { display: none; };
       .acf-fc-popup a[data-layout='layout_name_3'] { display: none; };
       .acf-fc-popup a[data-layout='layout_name_8'] { display: none; };
    <style>
    <? 
    endif;
    }
    add_action('admin_head', 'acf_flex_layouts_filter');
    

    You adapt it to your needs.
    We created arrays with Layouts to hide for every post types:

    
    $hide_laypout['post'] = array( 'lay1','lay2,'lay3'...);
    $hide_laypout['page'] = array( 'lay8','lay9' ...);
    $hide_laypout['movie'] = array( 'lay7','lay3' ...);
    etc etc ...
    

    And loop then inside <style> </style>.

    Not sure if is the best solution but works for us.

  • We tried lots of solutions here/there/anywhere and they didn’t work for us, we have a series of complex flex content fields and lots of custom post-types, not all layouts need to be used in all post types. We come out with this, maybe help someone:

    The basic idea is to hide the layout from the acf popup.
    This hides 3 layouts from the ACF Popup when you click ADD ROW in POSTS.

    
    function acf_flex_layouts_filter() {
    $type = get_post_type();
    if ($type=="post"): 
    ?>	
    <style>
       .acf-fc-popup a[data-layout='layout_name_1'] { display: none; };
       .acf-fc-popup a[data-layout='layout_name_3'] { display: none; };
       .acf-fc-popup a[data-layout='layout_name_8'] { display: none; };
    <style>
    <? 
    endif;
    }
    add_action('admin_head', 'acf_flex_layouts_filter');
    

    You adapt it to your needs.
    We created arrays with Layouts to hide for every post types:

    
    $hide_laypout['post'] = array( 'lay1','lay2','lay3'...);
    $hide_laypout['page'] = array( 'lay8','lay9' ...);
    $hide_laypout['movie'] = array( 'lay7','lay3' ...);
    etc etc...
    

    And loop then inside <style> </style>.

    Not sure if is the best solution but works for us.

    • Nik

    • May 24, 2019 at 1:21 pm

    The examples above were very helpful in guiding me to the solution I’ve landed on. Wanted to share in case it’s helpful for anyone else…

    In my functions.php, I define a constant that maps ACF flexible content layout names to arrays of allowed types and allowed (or blocked) IDs. Obviously the field’s display rules will override this. Note that if you’re using older versions of PHP, you’ll need to serialize and unserialize this array.

    define('ADMIN_ACF_LAYOUTS', [
        // show on all pages and posts
        'intro' => ['page', 'post'], 
        // show only on pages
        'testimonials' => ['page'], 
        // show on a specific page / post ID
        'faq' => [7],
        // show only on campsite post types and a specific page ID 
        // Example: "Our Campsites" page
        'map' => ['campsite', 12],
        // show on all pages *except* page ID 15 (note negative ID)
        'callouts' => ['page', -15],
    ]);

    In whatever file you prefer to define filters, replacing YOUR_ACF_FIELD_NAME with your specific Flexible Content field name:

    add_filter('acf/prepare_field/name=YOUR_ACF_FIELD_NAME', function($field) {
    
        global $post;
    
        // get the layout mapping, or an empty array 
        // just in case it's not defined
        $mapping = defined('ADMIN_ACF_LAYOUTS') ? ADMIN_ACF_LAYOUTS : [];
    
        // from John Huebner's clever approach...
        $layouts = $field['layouts'];
        $field['layouts'] = [];
    
        foreach ($layouts as $layout) {
    
            $key = $layout['name'];
    
            // if the layout name isn't in our mapping array
            // assume it available for all posts that the field rules allow
            if ( ! array_key_exists($key, $mapping)) {
                $field['layouts'][] = $layout;
                continue;
            }
    
            $allow_type = in_array($post->post_type, $mapping[$key]);
            $allow_id = in_array($post->ID, $mapping[$key]);
            $block_id = in_array(-1 * $post->ID, $mapping[$key]);
    
            // enable the layout if the current post type or post ID is allowed 
            // and the current ID is not explicitly excluded (note negative ID)
            if (($allow_type || $allow_id) && !$block_id) {
                $field['layouts'][] = $layout;
            }
        }
    
        return $field;
    });

    Hope this helps!

  • I will save that, I will be needing a way to do this myself soon. We also have a generic flex field that now has like 40 different layouts in it. I’m planning to create an admin options page where you can not only select the post types where this field group is displayed but also select what layouts to display on those pages. I plan to modify the location rules for the group when selecting post types, but your ideas may come in handy for filtering the layouts. It won’t be exactly the same because I’ll be getting the mapping from an options page, but it will be similar.

  • Thanks for all of the great direction guys! Wanted to add this here as well for anyone who wants to do this based on the page template. Still working on it, but this seems to be doing what we need for the moment:

    
    add_filter('acf/prepare_field/name=YOUR_ACF_FIELD_NAME', function($field) {
        
    global $post;
      
        $template = get_page_template_slug( $post->ID );
        $layouts = $field['layouts'];
        $field['layouts'] = array();
    
        if( $template == 'your-template-file.php' ) {
    
          foreach ($layouts as $layout) {
            if ($layout['name'] != 'specific_layout_1' && $layout['name'] != 'specific_layout_2') {
              $field['layouts'][] = $layout;
            }
          }
    
          return $field;
          
        } else {
    
          foreach ($layouts as $layout) {
              $field['layouts'][] = $layout;
          }
    
          return $field;
    
        }
    
    });
    
Viewing 11 posts - 1 through 11 (of 11 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.