Support

Account

Home Forums ACF PRO ACF conditional logic hide output in a foreach loop

Solved

ACF conditional logic hide output in a foreach loop

  • I am using a standard loop
    https://www.advancedcustomfields.com/resources/hiding-empty-fields/

    which outputs the field label and field values as table cells in a table.

    There are no Row Repeaters OR Field Groups with sub_fields.

    
    $out = '';
    $out .= '<div><table><tbody>';
    
    	$fields = get_field_objects();
    
    		if( $fields ){
    
    			foreach( $fields as $field ){
    			if( $field['value']){
    
    				$value = $field['value'];
    				if(is_array($value)) {
    				$value = @implode(', ', $value);
    				}
    
    				$out .= '<tr class="boat-tb-row"><td class="boat-tb-cell"><span class="acf-label">' . $field['label'] . '</span></td><td class="boat-tb-cell"><span class="acf-value">' . $value . '</span></td></tr>';
    			}
    
    		}
    
    	}
    
    $out .= '</tbody></table></div>';
    
    	return $out
    
    

    This is outputting all ACF field labels and values.

    One of the ACF fields is a checkbox list. ACF_Field_1 = checkbox array (1,2,3,4,5)

    ACF_Field_2 – Conditional logic – Show this field if [ACF_Field_1] > [value is equal to] > [4]

    Using the current for each loop, on the front end of my post, ACF_Field_2 is output on every post regardless of the conditional logic (ACF_Field_1 checkbox array does not include “4” )

    How do I account for the following in the for each loop.

    ACF_Field_1 if in_array(‘4’) include ACF_Field_2 in the foreach loop output.
    else hide ACF_Field_2 from the for each loop output

    My thought would be to php unset ACF_Field_2 from the array and run 2 seperate loops if {for each loop array_1 out . = } else { for each loop array_2 out. = }

    My understanding is that in this case I cannot use if (have_rows() while(have_rows() as this is related specifically to ACF Repeaters.

    I have been trolling Google for hours trying to find a specific case:
    Then I stumbled upon this post answer
    https://stackoverflow.com/questions/55221256/hide-certain-acf-fields-wordpress

    However, I don’t quite understand what the author has done in this answer and how to implement in the current loop.

    I’d be interested to know if there is a standard way of dealing with this in the ACF domain. As I could not find anything similar in the ACF support forum

    I am outputting the table using a [shortcode]
    Rather than having one long table, I am wanting to break apart the ACF Group into 3 [shortcodes] . . .
    [Specifications]
    [Features]
    [Options]

    I read some where there is not way to differentiate or segment fields using the ACF Layout Tab

    To achieve this am I better off
    1 – creating 3 separate Field Groups and displaying all 3 Field Groups to the Custom Post type and then segment my short codes using the Field Group Key “group_62eb60af9059d”.

    2 – Use a Layout Group ?

    3 – Naming my fields with a common denominator to differentiate sets of fields

    group1_field_name1
    group1_field_name2

    group2_field_name1
    group2_field_name2

    group3_field_name1
    group3_field_name2

    I look forward to your technical assistance.

    J 🙂

  • I have solved several issues using the following:

    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

    1 – ACF Field Setup

    I have setup fields as FILED TYPE > LAYOUT > GROUP
    https://www.advancedcustomfields.com/resources/group/

    This allows us to target the fields with a given ACF field group using the field group name.

            if( have_rows('group_name')){
                while(have_rows('group_name')){
                    the_row();  
    
                    if( $subfields = get_row()) {
    

    I am outputting the custom post type, ACF data, to a table using a foreach loop.
    The code is then displayed on our post using a [shortcode]

    <?php
    
    class CUSTOM_SHORTCODES {
    
    			public static function register_shortcodes() {
    				add_shortcode( 'custom_specs', array( __CLASS__, 'boat_specs' ) );
    			}
    
    public static function custom_specs($atts) {
      
    		$out = '';
    		$out .= '<div>';
    		$out .= '<table>';
    		$out .= '<tbody>';
    
    		$subfields = get_row();
    		$field = get_sub_field_object( $key );
    		if( have_rows('specifications')){
    			while(have_rows('specifications')){
    				the_row();  
    				if( $subfields = get_row()) {
    					foreach ($subfields as $key => $value) {
    						if ( !empty($value) ) {
    
    							if(is_array($value)) {
    							$value = @implode(', ', $value);
    							}
    							$field = get_sub_field_object($key);
    								$out .= '<tr class="tb-row"><td class="tb-cell"><span class="acf-label">' . $field['label'] . '</span></td><td class="tb-cell"><span class="acf-value">' . $value . '</span></td></tr>';
    						}
    					}  
    				}
    			}
    		}
    		$out .= '</tbody></table></div>';
    
    		return $out;
    	}	
    		
    }
    CUSTOM_SHORTCODES::register_shortcodes();
    

    In this instance, the demo shortcode is [custom_specs]

    In our foreach loop, we can check to see if a field has value. If it has no value i.e. null then the field does not show in our for each loop.

    if ( !empty($value) ) {
    OR
    https://www.advancedcustomfields.com/resources/hiding-empty-fields/

    If the returned value is an array, we can convert the array to a comma list.

    
    if(is_array($value)) {
    $value = @implode(', ', $value);
    }
    

    Using this method, we can segment our ACF data into different foreach loop shortcodes for our use case scenario.

    Specifications = [custom_specs]
    Standard Features = [custom_feat]
    Options = [custom_opt]

    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    2 – Omit / Remove ACF field from the foreach loop.

    The ‘price’ is recorded as an ACF field in our field group ‘specifications’.
    However, the client does not want to show the ‘price’ field on the table on the front end.

    How do we remove the ACF field ‘price’ from our ‘specifications’ foreach loop?

    OPTION 1 – “SIMPLE”
    Move the ACF field ‘price’ out of the current field group ‘specifications’ so it’s not returned in the shortcode loop [custom_specs].

    If OPTION 1 does not fit your requirements, then try this alternative.

    OPTION 2 – “ACF continue”
    ACF Support has come back with the following. Interestingly, there is no mention of this in the current ACF documentation.

    if( have_rows('specifications')){
                while(have_rows('specifications')){
                    the_row();  
    
                    if( $subfields = get_row()) {
    
                        foreach ($subfields as $key => $value) {
    
                                // Omit 'price' sub field - enter the field key
                                if ($key == 'field_123456789') { //skip this!
                                                    continue;
                                }
    

    Using the ACF field key and continue; we can now remove any ACF field inside our foreach loop.

    Fantastic!
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

    3 – Removing Conditional Logic Parent > Child ACF fields from our foreach loop.

    In this scenario, we have the PARENT FIELD1 and the CHILD FIELD2
    The fields can be any ACF field Type: Select, Checkbox, Radio Button, Button Group.

    PARENT FIELD1 (*Required? = Yes)
    ( ) ABC
    ( ) MNO
    ( ) XYZ > Show CHILD FIELD2

    CHILD FIELD2 (*Required? = Yes + Allow Null? = Yes )
    ( ) Choice 1
    ( ) Choice 2
    ( ) Choice 3

    We have conditional logic CHILD FIELD2
    Show this field if <PARENT FIELD1> Value is equal to <XYZ>

    Great!
    If PARENT FIELD1 (•) XYZ is selected, we expect CHILD FIELD2 Choices to show.
    If PARENT FIELD1 ( ) XYZ is de-selected, we can expect FIELD2 to hide.

    • • • • • • • • • • • • • • • • • • • • • •

    Now, this is where it gets tricky.

    As part of our strategy, we want to make it easy for the Client to update the data without making things worse.

    The Client Selects <PARENT FIELD1>(•) XYZ
    CHILD FIELD2 choices are shown.
    All choices are null – they are empty.
    The Client doesn’t make a selection from CHILD FIELD2 and updates the post.
    We get a validation warning – CHILD FIELD2 is set to (*Required) so now we have to make a selection.
    The Client selects CHILD FIELD2 (•) Choice 2
    We validate, and the post is saved.

    CHILD FIELD2 > Choice 2 is saved to the database.

    We run our shortcode loop and CHILD FIELD2 is output into our table.

    The Client decides, no, actually I didn’t want (•) XYZ, I really wanted ( ) ABC
    The Client de-selects ( ) XYZ and selects (•) ABC
    CHILD FIELD2 is hidden.

    Even though <PARENT FIELD1>( )XYZ is not selected, our foreach loop is still outputting CHILD FIELD2 in the table.

    Why ! – you ask?

    In the database CHILD FIELD2 still has a saved value = Choice 2.
    Our foreach loop condition is “only include fields that have value”.
    So CHILD FIELD2 is still showing.

    This stems from core ACF functionality – If the field is set to (*Required) ignore the null.
    https://github.com/elliotcondon/acf/issues/591

    How do we fix this?
    • • • • • • • • • • • • • • • • • • • • • •
    METHOD 1 – On all CHILD FIELD(s) disable (*Required)
    (*Required? = No)
    Each CHILD FIELD2 choice can be toggled ON or OFF. Allowing us to de-select our previous selected option. The post can be validated and saved without having a choice selected. The Database value is cleared on Post Update.

    But wait – this now requires the Client to understand that the CHILD FIELD2 needs to be un-selected before unselecting the PARENT FIELD1.

    LOL
    Sometimes the simplest of workflow solutions are the hardest for clients to remember.
    • • • • • • • • • • • • • • • • • • • • • •
    METHOD 2 – JQuery

    Use jQuery to null the CHILD FIELD when the PARENT FIELD is un-selected.

    This improves our Method 1 workflow, as the Client doesn’t have to remember to unselect the CHILD FIELD2. Our jQuery Function will handle this.

    For this to work, I changed my CHILD FIELD2 field Type to a ‘select’.
    When the Field Type ‘select’ is set to (Allow Null? = Yes) a null choice is added to the top of the dropdown select “-Select-“.
    https://www.advancedcustomfields.com/resources/select/
    I used JQuery to select the first item on the CHILD FIELD2 ‘select’ list
    when the Parent is de-selected.

    In my WordPress Child theme functions.php file I am loading a JS file when is_admin()

    define( 'CHILD_THEM_URI', get_stylesheet_directory_uri() );
    define( 'CHILD_THEM_DIR', get_stylesheet_directory() );
    // register scripts for the wp_admin section
    add_action( 'admin_head', 'register_admin_scripts' );
    function register_admin_scripts() {
        if ( is_admin() ) {
            wp_enqueue_script( 'admin_js', CHILD_THEM_URI . '/includes/admin.js', array( 'jquery' ) );
    
        }
    }

    In the JS File I have the following simple click function.

    
    jQuery(document).ready (function ($) {
    
    $('#parent_field_id').on('click',function () {
                    if ($(this).is(':checked')) {
                        //alert('You have Checked it');
                    } else {
                        //alert('You Un-Checked it');
                        // Set Conditional Select to null  - First Item on the list
                        $("#child_field_id").prop("selectedIndex", 0);
    
                    }
                });
    });
    

    • • • • • • • • • • • • • • • • • • • • • •

    METHOD 3 – delete_field()

    We could write a custom function if PARENT FIELD1 is de-selected then dynamically delete the conditional logic CHILD FIELD2 value from the database. Seems heavy to me!

    delete_field()
    delete_sub_field()

    Someone with better PHP skills than me may wish to provide a solution.
    I look forward to your responses.

    • • • • • • • • • • • • • • • • • • • • • •

    METHOD 4 – FUNCTION REQUEST

    Have an additional toggle option on the ACF CHILD FIELD next to the (AllowNull? = Yes) to turn ON or OFF the required functionality.

    If conditional logic PARENT Field is un-selected – return CHILD FIELD VALUES to the default Null State.

    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

    I think thats covers everything for now.

    Hopefully this helps someone else in the future

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

You must be logged in to reply to this topic.