Search code examples
jqueryadvanced-custom-fieldsattr

How to target an ACF field in a jQuery code inside à foreach loop?


How to target an ACF field in a jQuery code inside à foreach loop ?

Currently, posts are looping in a foreach loop. Each post presents a coach with photo, title, small description and a phone number. All of this elements are ACF custom fields which need to be filled in a back-office for each person.

At this point it's all right.

Phone number of each coach is hidden, the user needs to click on a button (which is an image "Show Number") to see the phone (which is another image as well). I'm using the .attr() jQuery function to replace the first image by the second one.

The problem : when the user clicks on any "Show Number" image, the last image number is displayed.

Expectation (Ex : Nicolas as 555-555-555 | Andrea as 555-485-784 | Melody as 555-124-332) Currently (Ex : Nicolas as 555-124-332 | Andrea as 555-124-332 | Melody as 555-124-332)

Any suggestions would be appreciated.

Thanks

foreach ($related_posts_articles as $related_post ){

    <div class="col-sm-6 col-md-6 col-lg-3 col-xs-12">

        <div>
            <a href="<?php echo get_permalink($related_post->ID); ?> ">
                <?php echo get_the_post_thumbnail($related_post->ID,"square-300",array('class' => 'img-responsive')); ?>   
            </a>
            <div>
                <a href="<?php echo get_permalink($related_post->ID); ?>">
                    <h2>
                        <?php echo wp_html_excerpt(strip_tags(get_field('acf_titre_mini', $related_post->ID)), 30, '...' ); ?>
                    </h2>
                </a>
                <div>
                    <?php echo wp_html_excerpt( strip_tags(get_field('acf_description_mini',$related_post->ID)), 129, '...' ); ?>    
                </div>

                <!-- START bloc -->
                <?php if( get_field('acf_numero_image', $related_post->ID) ): ?>
                    <div align="center">
                        <img class="input_img" src="<?php the_field('acf_btnVoirNum_image', $related_post->ID); ?>" >
                        <script>
                            jQuery(document).ready(function($) {
                                $(".input_img").click(function() {
                                    $(this).attr("src", "<?php the_field('acf_numero_image', $related_post->ID); ?>" );
                                });
                            });
                        </script>
                    </div>
                <?php endif; ?>
                <!-- END bloc -->
            </div>
        </div>
   </div>

}

Solution

  • The problem : when the user clicks on any "Show Number" image, the last image number is displayed.

    This is because you're adding a .click() handler in every iteration of your loop where if( get_field('acf_numero_image', $related_post->ID) ) is truthy, specifically this part:

    $(".input_img").click(function() {
        $(this).attr("src", "<?php the_field('acf_numero_image', $related_post->ID); ?>" );
    });
    

    If you view the page source for your rendered HTML, it's going to look something like the following:

    <!-- loop 1 -->
    <script>
        jQuery(document).ready(function($) {
            $(".input_img").click(function() {
                $(this).attr("src", "some_image_1.jpg" );
            });
        });
    </script>
    
    <!-- loop 2 -->
    <script>
        jQuery(document).ready(function($) {
            $(".input_img").click(function() {
                $(this).attr("src", "some_image_2.jpg" );
            });
        });
    </script>
    
    <!-- loop 3 -->
    <script>
        jQuery(document).ready(function($) {
            $(".input_img").click(function() {
                $(this).attr("src", "some_image_3.jpg" );
            });
        });
    </script>
    
    <!-- etc. -->
    

    Because you're adding another .click() handler every loop, when you click on .input_img, it's going to go through each of your click handlers and change the src to some_image_1.jpg, then some_image_2.jpg, and so on, until it reaches the last one, hence why it appears to only display the last image number.

    Using a custom data- attribute and moving the .click() handler outside of the loop will fix this - abridged example below:

    <?php
        foreach ($related_posts_articles as $related_post) {
    
            // wrapper <div> / other HTML here
    
            ?>
                <!-- START bloc -->
                <?php if (get_field('acf_numero_image', $related_post->ID)): ?>
                    <div align="center">
    
                        <!--
                            Adding custom data-acf-numero-image attribute here containing field value
                        -->
                        <img class="input_img" src="<?php the_field('acf_btnVoirNum_image', $related_post->ID); ?>" data-acf-numero-image="<?php the_field('acf_numero_image', $related_post->ID); ?>" />
    
                    </div>
                <?php endif; ?>
                <!-- END bloc -->
            <?php
    
            // closing <div> elements here
        }
    ?>
    
    <!--
        One single block of JS to handle all clicks to .input_img, rather than adding
        duplicate click handlers inside the foreach loop:
    -->
    <script>
        jQuery(document).ready(function($) {
            $(".input_img").click(function() {
                // Get "acf_numero_image" value from custom data- attribute
                var acfNumeroImage = $(this).attr("data-acf-numero-image");
    
                // Update src attribute with custom acf_numero_image
                $(this).attr("src", acfNumeroImage);
            });
        });
    </script>