Support

Account

Home Forums Add-ons Repeater Field Unique ID for Repeater Field

Solved

Unique ID for Repeater Field

  • I’m not sure if this is even possible, but I’m hoping someone can help me out.

    I’m creating a Privacy Policy page utilizing the repeater field, the client is looking to have a numbered section that scrolls down to the content, the numbered list will be just section titles, and then it will scroll to the remaining content.

    So:

    #1 – Policy Title 1

    #2 – Policy Title 2

    On-click, scroll to

    #1 – Policy Title 1
    Some content here…

    #2 – Policy Title 2
    Some content here…

    And so on, and so forth.

    Now, how would I be able to display a unique name=”section-1″ section on the link when using a repeater field without having to have one manually created by the client? (New to WP, trying to keep it as simple as humanly possible for them).

    So, how would I go about outputting like section-1, section-2, section-3 for the links?

    I’m calling the repeater field twice, once for just the titles, and then below to echo the remaining content.

    Is this even possible?

    Note: I did attempt to search for this on the old forums but the Search function would not go through, if this has already been answered – please let me know.

  • Hi @Krissy S.

    No worries, here is the example from the docs with some extra PHP to create a counter:

    
    <?php if(get_field('repeater_field_name')): $i = 0; ?>
    
    	<ul>
     
    	<?php while(has_sub_field('repeater_field_name')): $i++; ?>
    		
    		<li class="section-<?php echo $i; ?>">
    			sub_field_1 = <?php the_sub_field('sub_field_1'); ?>, sub_field_2 = <?php the_sub_field('sub_field_2'); ?>, etc
    		</li>
     
    	<?php endwhile; ?>
     
    	</ul>
     
    <?php endif; ?>
    
  • Thank you Elliot, this worked beautifully.

  • Hi!,

    I’m having a similar problem where I try to associate a sub field to a unique ID.

    In the DB, I see that I have a meta_key like repeater_field_0_sub_field where 0 is the order index. If, later on, I change the order of the sub fields, the meta_key become something like repeater_field_2_sub_field and event the meta_id change. So I have no way to “hook” to a sub field.

    Am I missing something?

    Update! I just saw this topic. I’ll probably try to update @gelform ‘s for V5…if there’s no other way 🙂

    Thanks!

    P.S.: Awesome plugin! I use it in all my projects.
    Using ACF Pro V.5

  • Thanks for this code Elliot, it works just as I wanted. Not sure if you can help with this but I’ve got a related problem.

    I’m creating a list of tabs with the repeater field and using the psuedo-class :checked to give the selected tab a different background colour.

    The problem is that when using the repeater field the last tab rendered is the one selected when the user arrives on the page. What I’d like to happen is the first tab be selected instead.

    My code is below and you can see it in operation here: http://londonsleepcentre.ae/sleep-apnea-osa-treatment-services/mandibular-devices/

    
        <div class="tabs">
          <?php if(get_field('additional_content')): $i = 0; ?>
            <?php while(has_sub_field('additional_content')): $i++; ?>
                <input type="radio" name="tabs" id="tab<?php echo $i; ?>" checked />
                <label for="tab<?php echo $i; ?>" class="<?php the_sub_field('field_label'); ?>"><?php the_sub_field('extra_title'); ?></label>
            <?php endwhile; ?>
          <?php endif; ?> 
          <?php if(get_field('additional_content')): $i = 0; ?>
            <?php while(has_sub_field('additional_content')): $i++; ?>
              <div id="tab-content<?php echo $i; ?>" class="tab-content">
                  <?php the_sub_field('extra_content'); ?>
              </div> <!-- #tab-content1 -->        
            <?php endwhile; ?>
          <?php endif; ?> 
        </div>
    
    
  • Hey Dave,

    What a coincidence seeing you here – ha!

    The way to do that is check if it’s the first iteration of the while loop:

    
    <div class="tabs">
    	<?php if(get_field('additional_content')): $i = 0; ?>
    		<?php while(has_sub_field('additional_content')): $i++; ?>
    				<input type="radio" name="tabs" id="tab<?php echo $i; ?>"<?php if($i == 0) { echo " checked"; };?> />
    				<label for="tab<?php echo $i; ?>" class="<?php the_sub_field('field_label'); ?>"><?php the_sub_field('extra_title'); ?></label>
    		<?php endwhile; ?>
    	<?php endif; ?> 
    	<?php if(get_field('additional_content')): $i = 0; ?>
    		<?php while(has_sub_field('additional_content')): $i++; ?>
    			<div id="tab-content<?php echo $i; ?>" class="tab-content">
    					<?php the_sub_field('extra_content'); ?>
    			</div> <!-- #tab-content1 -->        
    		<?php endwhile; ?>
    	<?php endif; ?> 
    </div>
    
  • Just an FYI for more advanced usage cases, for example where you have multiple repeaters on the same page in flexible content and you need unique ID’s for each block(for example to target bootstrap modals or collapse elements) you can do something like this:

    <section class="faq-block <?php if (get_sub_field('background') == 'blue'): ?> blue-bg<?php else: ?><?php endif; ?>">
        <div class="container">
            <div class="row text-center">
                <div class="col-md-10 col-md-offset-1">
    
                    <h2 class="section-heading"><?php the_sub_field( 'section_heading' ) ?></h2>
    
                    <div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
                       <?php
                       //$uniqueid = get_sub_field( 'faq_unique_id' );
                       $uniqueid = uniqid('faq_items');
                       $count = 0;
                       while ( have_rows( 'faq_items' ) ) : the_row(); ?>
                       <div class="panel panel-default listbox">
                        <div class="panel-heading" role="tab" id="headingTwo">
                            <h3 class="panel-title">
                                <a data-toggle="collapse" data-parent="#accordion"
                                href="#collapse-<?php echo esc_attr( $uniqueid ); ?>-<?php echo esc_attr( $count ); ?>"
                                aria-expanded="false">
                                <?php the_sub_field( 'faq_question' ) ?>
                            </a>
                        </h3>
                    </div>
                    <div id="collapse-<?php echo esc_attr( $uniqueid ); ?>-<?php echo esc_attr( $count ); ?>"
                        class="panel-collapse collapse" role="tabpanel">
                       <div class="panel-body">
                        <p><?php the_sub_field( 'faq_answer' ) ?></p>
                    </div>
                </div>
            </div>
            <?php $count ++; ?>
    
        <?php endwhile; ?>
    
    </div><!--end panel group-->
    
    </div>
    </div>
    </div>
    </section>
  • Where

    $uniqueid = uniqid('faq_items');

    sets a variable by pulling the ACF unique ID of a repeater in a flex block called faq_items

    and

    <div id="collapse-<?php echo esc_attr( $uniqueid ); ?>-<?php echo esc_attr( $count ); ?>

    echos that out in the frontend and also increments the repeater rows.

  • I am trying your method but it is outputting the same unique ID per repeater row and not a unique ID ?

    <div class="accordian">
    
    				<?php
    
    				 $uniqueid = uniqid('question');
    				 $count = 0;
    
    				while ( have_rows( 'layout_nine_questions' ) ) : the_row(); ?>
    
    <div class="accordian_single">
    <input type="checkbox" id="<?php echo esc_attr( $uniqueid ); ?>">
    <label class="accordian-label" for="<?php echo esc_attr( $uniqueid ); ?>"><?php the_sub_field( 'layout_nine_question' ); ?></label>
    <div class="accordian-content">
    <?php the_sub_field( 'layout_nine_answer' ); ?>
    </div>
    </div>
    <?php $count ++; ?>
    				<?php endwhile; ?>
    			<?php else : ?>
    				<?php // no rows found ?>
    			<?php endif; ?>
    </div>
    
    			</div>
  • Don’t use uniqid() with the same input and expect different output on consecutive calls within a for/while loop—see https://www.php.net/manual/en/function.uniqid.php#120123.

    The uniqid() function is part of the standard PHP library and has no relation or knowledge of ACF, and so does not in any way set “a variable by pulling the ACF unique ID of a repeater in a flex block” as @pierrebalian claims. It simply outputs a “random” string based on the current microseconds and any seed you feed it.

    If you must use uniquid() at least feed it some value from your repeater within the loop so that you can reasonably expect it to be different each time. Both @pierrebalian and @waynep16 are generating a single random string once and outputting it within the loop, which will obviously output the same value each time.

    The better option is to use a hashing function like md5() along with serialize() to not only generate unique strings, but also ensure that they are the same id each page load. This method creates a hash for the full repeater/flexible content field row. You can also use substr() to reduce the length to something manageable, like 8 characters, and still be reasonably sure that you’ll get unique values each time.

    
    <?php
    $rows = array();
    while ( have_rows( 'repeater_or_flex_content' ) ) : $row = the_row(true); // pass true to get formatted subfields
    	$id = substr( md5( serialize( $row ) ), 0, 8 ); // outputs something like '35f841ff'
    	$rows[$id] = $row; // store the $row for use elsewhere with the id
    ?>
    	<div id="panel-<?php echo $id; ?>" aria-labeledby="tab-<?php echo $id; ?>" role="tabpanel">
    		<?php the_sub_field( 'tab_content' ); ?>
    	</div>
    <?php
    endwhile;
    
    // Later, when building tabs
    foreach ( $rows as $r ) :
    ?>
    	<button id="tab-<?php echo $r['id]; ?>" role="tab" aria-controls="panel-<?php echo $r['id']; ?>"><?php echo $r['tab_title']; ?></button>
    <?php
    endforeach;
    

    Of course you can reverse this approach so you’re outputting tabs first, storing the rows, and using them later to output the tab content, but hopefully you get the gist.

  • Don’t use uniqid() with the same input and expect different output on consecutive calls within a for/while loop—see https://www.php.net/manual/en/function.uniqid.php#120123.

    The uniqid() function is part of the standard PHP library and has no relation or knowledge of ACF, and so does not in any way set “a variable by pulling the ACF unique ID of a repeater in a flex block” as @pierrebalian claims. It simply outputs a “random” string based on the current microseconds and any seed you feed it.

    If you must use uniquid() at least feed it some value from your repeater within the loop so that you can reasonably expect it to be different each time. Both @pierrebalian and @waynep16 are generating a single random string once and outputting it within the loop, which will obviously output the same value each time.

    The better option is to use a hashing function like md5() along with serialize() to not only generate unique strings, but also ensure that they are the same id each page load. This method creates a hash for the full repeater/flexible content field row. You can also use substr() to reduce the length to something manageable, like 8 characters, and still be reasonably sure that you’ll get unique values each time.

    
    <?php
    $rows = array();
    while ( have_rows( 'repeater_or_flex_content' ) ) : $row = the_row(true); // pass true to get formatted subfields
    	$id = substr( md5( serialize( $row ) ), 0, 8 ); // outputs something like '35f841ff'
    	$rows[$id] = $row; // store the $row for use elsewhere with the id
    ?>
    	<div id="panel-<?php echo $id; ?>" aria-labeledby="tab-<?php echo $id; ?>" role="tabpanel">
    		<?php the_sub_field( 'tab_content' ); ?>
    	</div>
    <?php
    endwhile;
    
    // Later, when building tabs
    foreach ( $rows as $r ) :
    ?>
    	<button id="tab-<?php echo $r['id]; ?>" role="tab" aria-controls="panel-<?php echo $r['id']; ?>"><?php echo $r['tab_title']; ?></button>
    <?php
    endforeach;
    

    Of course you can reverse this approach so you’re outputting tabs first, storing the rows, and using them later to output the tab content, but hopefully you get the gist.

  • Hi,

    Would anyone be able to adjust elliots initial code, but for a nested repeater? I’m looking to use ACF to create a restaurant menu where each part of the menu is toggled with tabs. The first sub fields are each menu (lunch dinner etc) then the next sub fields under the next rows are the dishes.

    Thanks

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

The topic ‘Unique ID for Repeater Field’ is closed to new replies.