• Resolved dock00

    (@dock00)


    How to display repeatable fields inside a group?
    Search this for hours, but can’t figure out.
    Help docs are not very clear on this issue.

    custom fields:

    /**
    	 * Repeatable Field Groups
    	 */
    	$cmb_group = new_cmb2_box( array(
    		'id'           => 'metabox',
    		'title'        => __( 'Repeating Field Group', 'cmb2' ),
    		'object_types' => array( 'discography', ),
    	) );
    
    	// $group_field_id is the field id string, so in this case: $prefix . 'demo'
    	$group_field_id = $cmb_group->add_field( array(
    		'id'          => $prefix . 'discography_group',
    		'type'        => 'group',
    		'description' => __( 'Generates reusable form entries', 'cmb2' ),
    		'options'     => array(
    			'group_title'   => __( 'Entry {#}', 'cmb2' ), // {#} gets replaced by row number
    			'add_button'    => __( 'Add Another Entry', 'cmb2' ),
    			'remove_button' => __( 'Remove Entry', 'cmb2' ),
    			'sortable'      => true, // beta
    		),
    		'fields'      => array(
    		                    array(
    					'name' => __( 'Title', 'deejay' ),
        					'id'   => 'track_title',
        					'type' => 'text'
    					),
    				array(
    					'name' => __( 'Label', 'deejay' ),
    	    				'id'   => 'track_label',
    	    				'type' => 'text'
    				),
    				array(
    					'name' => __( 'Buy it on', 'deejay' ),
    					'id'   => 'buy_link',
    					'type' => 'text',
    					'repeatable' => true
    						),
    			),
    	) );

    for the front-end:

    <?php $discography_group = get_post_meta( get_the_ID(), '_cmb2_discography_group', true ); ?>
    
    		<ul>
    			<?php foreach ( (array) $discography_group as $key => $entry ) {
    
    		    		$label = $title = $buy = '';
    
    				if ( isset( $entry['track_label'] ) ) {
    					$label = esc_html( $entry['track_label'] );
    				}
    				if ( isset( $entry['track_title'] ) ) {
    					$title = esc_html( $entry['track_title'] );
    				}
    				if ( isset( $entry['buy_link'] ) ) {
    					$buy = esc_html( $entry['buy_link'] );
    				}
    
    				?>
    
    				<li>
    					<h1><?php echo $discography_group [$key]['track_title'] ?></h1>
    					<p><?php echo $discography_group [$key]['track_label'] ?></p>
    
    					<a href="<?php echo $discography_group [$key]['buy_link'] ?>" target="_blank" class="float-right"></a>
    
    				</li>
    			<?php } ?>
    
    		</ul>

    thanks in advance for any help.

    https://www.ads-software.com/plugins/cmb2/

Viewing 11 replies - 1 through 11 (of 11 total)
  • Plugin Contributor Michael Beckwith

    (@tw2113)

    The BenchPresser

    From the looks of your code/settings, $entry[‘buy_link’] ends up being an array any time you have anything set for a buy link, even just 1. You’d need to loop over $entry[‘buy_link’] like you already are $discography_group.

    Thread Starter dock00

    (@dock00)

    I solved it like this.

    <?php $discography_group = get_post_meta( get_the_ID(), '_cmb2_discography_group', true ); ?>
    
    		<ul>
    			<?php foreach ( $discography_group as $value ) { ?>
    
    				<li>
    					<h1><?php echo $value['track_title'] ?></h1>
    					<p><?php echo $value['track_label'] ?></p>
    
    					<?php $link = $value['buy_link']; ?>
    						<?php foreach ( $link as $value_link) { ?>
    							<a href="<?php echo $value_link ?>" target="_blank" class="float-right"></a>
    						<?php } ?>
    
    				</li>
    			<?php } ?>
    
    		</ul>

    Any advice to improve the code or this is sufficient?
    Thanks

    Plugin Contributor Michael Beckwith

    (@tw2113)

    The BenchPresser

    Looks fine to me, not much room to improve there. If anything, provide the <a> tag with something to click. Right now it’s empty.

    Thread Starter dock00

    (@dock00)

    yep, the <a> tag will have something for sure, just testing.
    Thanks

    Hi there. Thanks for posting your code, it helped me a lot! Indeed the CMB2 documentation is not so self explanatory for those new comers to php development like me. I was looking for a way to conditionally display some price boxes within my theme .php templates…

    This is how I’ve set up the repeatable group, I couldn’t retrieve and output any repeatable field though as they always return an Array instead of the repeatable field’s value, even looping through them with <?php foreach.

    $cmb_group = new_cmb2_box( array(
              'id'            => $prefix . 'food_price_box',
              'title'         => __( 'Pricing Options', 'pivot' ),
              'object_types'  => array( 'food_menu' ),
            ) );
    
            // Parent
            $group_field_id = $cmb_group->add_field( array(
              'id'          => $prefix . 'food_price_group',
              'type'        => 'group',
              'options'     => array(
              'group_title'   => __( 'Price {#}', 'cmb2' ),
              'add_button'    => __( 'Add New Price', 'mrancho' ),
              'remove_button' => __( 'Remove Price', 'mrancho' ),
              'sortable'      => true, // beta
            ),
              ) );
    
            // Price Label
            $cmb_group->add_group_field( $group_field_id, array(
              'name' => __('Price Title', 'mrancho'),
              'desc' => __('Set a short label for the price. e.g Small, Large, Square', 'pivot'),
              'id'   => 'price_title',
              'type' => 'text_small',
              //'repeatable' => true, // Repeatable fields are supported w/in repeatable groups (for most types)
              ) );
    
            // Price Label Description
            $cmb_group->add_group_field( $group_field_id, array(
              'name' => __('Price Description', 'mrancho'),
              'desc' => __('Set a very short description for the price label. e.g 4 slices, 500ml, 1 kilo', 'pivot'),
              'id'   => 'price_desc',
              'type' => 'text_small',
              //'repeatable' => true, // Repeatable fields are supported w/in repeatable groups (for most types)
              ) );          
    
            // Price Amount
            $cmb_group->add_group_field( $group_field_id, array(
              'name' => __( 'Product Price', 'mrancho' ),
              'desc' => __('Set the price for the item. Use , to separate decimals.', 'pivot'),
              'id'   => 'price_tag',
              'type' => 'text_money',
              'before_field' => 'R$', // override '$' symbol if needed
              //'repeatable' => true, // Repeatable fields are supported w/in repeatable groups (for most types)
              ) );

    And this is the code that I ended up with for displaying the fields within the group:

    $food_prices = get_post_meta( $post->ID, '_prefix_food_price_group', true );

    <?php
    foreach( (array) $food_prices as $key => $value ){
        if(!( isset( $value['price_tag'] ) ))
           continue;
                echo '<div class="col-xs-12 col-md-4">';
    
                echo '<div id="weather-widget" class="panel">';
                echo '<div class="panel-heading text-center">';
                echo '<div id="current">';
                echo ' '. $value['price_tag'] .' ';
                echo '</div>';
                echo '<p>Here will be displayed another field's value</p>';
                echo '</div>';
    
                echo '<div class="panel-footer">';
    
        if(!( isset( $value['price_title'] ) ))
           continue;
    		   echo '<div id="hiTemp" class="col-xs-6 text-center">' . $value['price_title'] . '</div>';
    
        if(!( isset( $value['price_desc'] ) ))
           continue;
    		   echo '<div id="hiTemp" class="col-xs-6 text-center">' . $value['price_desc'] . '</div>';
    
    		   echo '<div class="clearfix">';
    		   echo '</div>';
    		   echo '</div>';
    
    		   echo '</div>';
                       echo '</div>';
    }
    ?>

    So far this code sets up a (repeatable) group and then I can retrieve their values, but no success at all on retrieving an individual repeatable field within the group.

    Also, the code is acting weird on the Post edit screen because if I leave all fields blank, CMB2 text money field is kind of insisting to save a value of 0,00, so when viewing my theme all the posts for which the custom fields haven’t being filled/saved are getting a price box with a “0,00” in the front end…

    This is an issue I couldn’t solve yet, not sure though it’s a theme thing or a CMB2 bug or something else…

    Thanks in advance WP Community! If someone would like to review my code and suggest a better logic and/or enhancements it is pretty much appreciated!

    Plugin Contributor Michael Beckwith

    (@tw2113)

    The BenchPresser

    Just a quick note, if you’re still getting “Array” back when you try to echo something, that means there’s still nested arrays to work through. The individual string values are there eventually, just a question of when. Utilize the print_r()/var_dump() functions as well to inspect what’s stored in a given variable.

    I haven’t yet tried to see what’s resulting with the code above, just giving a quick note for now.

    Hey Michael Beckwith, thanks for the input. I’ll certainly read about the functions. I’d really like to see
    a more rich, comprehensive CMB2 documentation, as a designer myself I found out that CMB2 is simply amazing! It is so nice to be able to power WordPress even more without being an expert developer.

    Although now I’m able to create stuff I thought I would never be able to do, it’s being a nightmare for me to get to the very basic of repeatable fields usage.

    So far what I’ve learnt about the CMB2 group usage haven’t helped me in a very intuitive way, I mean, if I set up a group with #3 repeatable fields I will repeat each field within a group until I comply with the amount of information a certain post needs, and I’ll not keep repeating the group itself. I’m not sure if I understand its correct usage, I’ll keep studying CMB2 documentation anyway.

    Here’s what I’ve accomplished so far… I’ve linked the screenshots bellow:

    – The Post Edit Screen with the fields in place: See.
    – The Fields displayed on the theme: See.

    – The bug I’ve encountered where posts for which the fields are not filled/saved, the text money field insists to show up a value of 0,00: See.

    I invite everyone willing to spread the knowledge to come here and share their repeatable fields set up code snippets so others who are still beginning with CMB2 can have a good quality reference. This topic saved my day, maybe saves your too.

    Thanks everyone!

    Plugin Contributor Michael Beckwith

    (@tw2113)

    The BenchPresser

    I am not managing to figure out why it insists on the default value. As a bit of a workaround for it, you could check to see if the value equals “0,00” before output and base your output on that.

    if ( '0,00' != $price ) {
        echo $price;
    }

    It would only echo the $price variable if it does NOT equal that default. Just a thought to hopefully get you moving forward.

    Hey Michael Beckwith, thanks for the input! My theme already uses CMB2 and it has a wide vary of custom functions around it, perhaps it’s something related to those functions, not sure though. I’ll try the workaround you’ve suggested to see if I can get rid of this minor annoyance.

    Meanwhile, how in the world am I able to output a repeatable field within a group, please see the screenshot.

    I mean, let’s suppose I’ve got a Pricing Options metabox with a Pricing Group, which in turn has a few custom fields… I’d like to keep repeating the fields within the group and not the group itself, is this even possible?

    I’ve tried all sorts of solutions I’ve come across, I’m now reading php array() docs in order to see if I can accomplish it, I think I need to work through the nested arrays as you mentioned earlier, right? How can I accomplish that taking as base the following code, which always returns Array()?

    <?php
    
    $food_prices = get_post_meta( $post->ID, '_ebor_food_price_group', true );
    
        echo '<ul>';
    foreach ( (array) $food_prices as $key => $entry ) {
     $price_title = array();
     if ( isset( $entry['price_title'] ) )
     $price_title = $entry['price_title'];
        echo '<li>';
        echo '<p>' . $price_title . '</p>';
        echo '</li>';
     }
        echo '</ul>';
    
    ?>
    Plugin Contributor Michael Beckwith

    (@tw2113)

    The BenchPresser

    Like I mentioned earlier, if you’re getting “Array” as your echo’d output, then there is at least one more nested array to get through. I would instead do a quick test with print_r() on that value you’re trying to echo, and inspect what is inside it. If I recall right, there are frequently cases of $somevariable being an array with only 1 key/value pair in it, and you would be able to echo that value using $somevariable[0] to reference that 1 key/value pairing.

    Hey Michael Beckwith! Thank you very much for your tips! I’ve tried the var_dump() and print_r() functions, and at first by inspecting the echo’d results I succeed on outputting a repeatable field which were not within a repeatable group. What I mean is I’ve managed to output a repeatable field which were set up within an ordinary metabox.
    E.g.

    // The following outputs a repeatable field within an ordinary metabox (not a group), just had to create a loop within a loop
    <?php
    $food_titles = array(get_post_meta($post->ID, '_prefix_price_legend', true));
    foreach ( $food_titles as $key => $ftitle ) {
        if(!( isset( $ftitle ) ))
           continue;
      foreach ($ftitle as $title ) {
    		   echo '<p>' . $title . '</p>';
      }
    }
    //print_r($ftitle);
    ?>
    // The following will do the same as the code above, but one can check individually for the keys of an array within a $variable
    <?php
    $food_titles = array(get_post_meta($post->ID, '_prefix_price_legend', true));
    foreach ($food_titles as $key => $ftitle ) {
       if(!( isset($ftitle[0]) ))
          continue;
       echo '<p>' . $ftitle[0] . '</p>';
       if(!( isset($ftitle[1]) ))
          continue;
          echo '<p>' . $ftitle[1] . '</p>';
       if(!( isset($ftitle[2]) ))
          continue;
             echo '<p>' . $ftitle[2] . '</p>';
    }
    //print_r($ftitle);
    ?>

    So, by testing the function print_r($ftitle); this is what I got:

    Array
    (
        [price_title] => Array
            (
                [0] => Small
                [1] => 4 Slices
            )
    
        [price_desc] => Serves up to 2 people
        [price_tag] => 28,90
    )

    The above code was a starting point for testing purposes only, then I had to find out a way to output a repeatable field within a CMB2 repeatable group…

    Regarding my specific scenario, it is consisted of a repeatable group with 4 fields, in which only the field with 'id' => 'price_title' is set as repeatable. Here’s how I’ve set up the repeatable group.

    On my previous code the foreach loop was returning a nested array, at least I believe it is called like that based on what I’ve read so far… I was not able to output that specific repeatable field values because the field itself was an array inside another main array, in this case, all I had to do was to set the repeatable field within a $variable and then, within the main loop I created a new one to loop through the repeatable field.

    // Loop through the repeatable group's array
    <?php
    foreach( (array) $food_prices as $key => $value ){
        if(!( $food_prices ))
           continue;
                echo '<div class="col-xs-12 col-md-4">';
    
                echo '<div id="food-widget" class="panel">';
                echo '<div class="panel-heading text-center">';
                echo '<div id="food-price">';
                echo ' '. $value['price_tag'] .' '; // This field lies within the group's main array, so no need to loop through it
                echo '</div>';
        if(!( isset( $value['price_desc'] ) ))
           continue;
                echo '<p>' . $value['price_desc'] . '</p>';
                echo '</div>';
    
                echo '<div class="panel-footer">';
    $entrytitle = (array) $value['price_title'];  // set a variable for the repeatable field that exists within the repeatable group, it implies that the field has an array that lies within the group's main array, in this case it is true
        if(!( isset( $entrytitle ) ))
           continue;
    foreach ($entrytitle as $title ) { // Loop through the repeatable field array
    		   echo '<div id="hiTemp" class="col-xs-6 text-center">' . $title . '</div>';
    }
    		   echo '<div class="clearfix">';
    		   echo '</div>';
    		   echo '</div>';
    
    		   echo '</div>';
    
    		   echo '</div>';
    
    // print_r($value);
    }
    ?>

    print_r($value);
    returns the following:

    Array
    (
        [price_title] => Array
            (
                [0] => Small
                [1] => 4 Slices
                [2] => Yeah I got it!
            )
    
        [price_desc] => Serves up to 2 people
        [price_tag] => 28,90
        [check_promo] => Array // Look what I found here, another array!
            (
                [0] => yes
                [1] => no
            )
    
    )

    Well that’s it. For now I’m quite happy with the fact it is working. Indeed getting to it was quite difficult and I’m sure there might be a lot of inconsistencies in my code, so I kindly invite the expert developers to point us out on how to produce a better and enhanced function/snippet to improve the retrieving of repeatable fields within a group.

    Thanks everyone!

Viewing 11 replies - 1 through 11 (of 11 total)
  • The topic ‘Display repeatable field inside group’ is closed to new replies.