Search code examples
javascriptphpwordpressadvanced-custom-fieldsacfpro

Populate Select Field based on ACF Repeater Text Input Choice


I am struggling a bit with this and could use some help. I have an ACF repeater called "gas_grades" and within that repeater I have two fields:

First filed is "grade" and is a text field. Second field is "size" and is a repeater field with a text field.

So, on an individual post I can add the gas grades, and the sizes. 5.5, 6, 6.5, 7, etc.

What I'm attempting to accomplish here is to loop through the grades in a form select field and based on the grade selected in the dropdown will display the sizes for that specific grade in a second dropdown.

The image below demonstrates the current layout of my field group.

Repeater (Gas Grades) Text Field (Grade) Repeater (Size) Text Field (Size) End Repeater (Grade) End Repeater (Gas Grades)

enter image description here

This is the basic repeater loop used to display the data:

@if( have_rows('gas_grades') )
    @while( have_rows('gas_grades') )
        
            <?php
            the_row();
            $grade = get_sub_field('grade');
            ?>
            <option value="">{{ $grade }}</option>
            
            @if( have_rows('size') )
                @while( have_rows('size') )
                    <?php
                    the_row();
                    $size = get_sub_field('size');
                    ?>
                        <option value="">{{ $size }}</option>
                @endwhile
            @endif
        
    @endwhile
@endif

And then of course, this is the current output:

enter image description here

So, 5.5, 6, and 6.5 would be listed in the first select dropdown, then their sub-repeater fields would be listed in the 2nd dropdown.


Solution

  • You can do this using JQuery.

    First, you have to create two separate dropdowns.

    Create a dropdown for only grades.

    if( have_rows('grades') ): ?>
        <select id="grades">
            <?php while( have_rows('grades') ) : the_row(); $grade = get_sub_field('grade'); ?>
                <option value="<?php echo $grade; ?>"><?php echo $grade; ?></option>
            <?php endwhile; ?>
        </select>
    <?php else : endif; ?>
    

    Create dropdown for only sizes but with using data attr. add a grade in data attr called `data-group.

    <?php if( have_rows('grades') ): ?>
        <select id="sizes">
            <?php while( have_rows('grades') ) : the_row();
                $grade = get_sub_field('grade');
                if( have_rows('sizes') ): while( have_rows('sizes') ) : the_row();
                    $size = get_sub_field('size'); ?>
                        <option data-group="<?php echo $grade; ?>" value="<?php echo $size; ?>"><?php echo $size; ?></option>
                <?php endwhile; ?>
                <?php else : endif; 
            endwhile; ?>
        </select>
    <?php else : endif; ?>
    

    Now you need to filter size dropdown based on grade select on grade change event.

    <script type="text/javascript">
        (function($){
            $('#grades').on('change', function(){
                var grade = $(this).val();
                var size  = $('#sizes');
                var i     = 1;
                $('option', size).filter(function(){
                    if ( $(this).attr('data-group') === grade ) {
                        $(this).show();
                        if( i == 1 ){
                            $("#sizes").val($(this).val());
                        }
                        i++;
                    } else {
                        $(this).hide();
                    }
                });
            });
            $('#grades').trigger('change');
        })(jQuery);
    </script>
    

    $('#grades').on('change', function(){
        var grade = $(this).val();
        var size  = $('#sizes');
        var i     = 1;
        $('option', size).filter(function(){
            if ( $(this).attr('data-group') === grade ) {
                $(this).show();
                if( i == 1 ){
                  $("#sizes").val($(this).val());
                }
                i++;
            } else {
                $(this).hide();
            }
        });
    });
    $('#grades').trigger('change');
            
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <select id="grades">
        <option value="5.5">5.5</option>
        <option value="6">6</option>
        <option value="6.5">6.5</option>
    </select>
    <select id="sizes">
        <option data-group="5.5" value="44L/ Size 200 : 55 lbs">44L/ Size 200 : 55 lbs</option>
        <option data-group="5.5" value="265 AL : 60/40 lbs">265 AL : 60/40 lbs</option>
        <option data-group="5.5" value="150 AL : 28 lbs ">150 AL : 28 lbs </option>
        <option data-group="6" value="45L/ Size 200 : 55 lbs">45L/ Size 200 : 55 lbs</option>
        <option data-group="6" value="270 AL : 60/40 lbs">270 AL : 60/40 lbs</option>
        <option data-group="6" value="200 AL : 28 lbs ">200 AL : 28 lbs </option>
        <option data-group="6.5" value="50L/ Size 200 : 55 lbs">50L/ Size 200 : 55 lbs</option>
        <option data-group="6.5" value="300 AL : 60/40 lbs">300 AL : 60/40 lbs</option>
        <option data-group="6.5" value="200 AL : 28 lbs ">200 AL : 28 lbs </option>
    </select>