CMB2 new repeatable WYSIWYG fields not initializing

CMB2 is great for adding your own fields (custom meta boxes) to WordPress.
When implementing a repeater group with a (WP tinyMCE) WYSIWYG editor I ran into an issue with adding a new group. The new WYSIWYG wouldn’t load (initialize properly). Only after saving the form in WordPress. At the time of writing this issue doesn’t seem to be fixed yet. I did find a patch by Arkytn which fixes this issue.

Example php code in function.php to create a repeater group with a title field and a WYSIWYG field:
(replace status201 with your own prefix)

/**
 * Get the bootstrap (when including cmb2 inside your theme)! If using the plugin from wordpress.org, REMOVE THIS!
 */

if ( file_exists( dirname( __FILE__ ) . '/cmb2/init.php' ) ) {
	require_once dirname( __FILE__ ) . '/cmb2/init.php';
} elseif ( file_exists( dirname( __FILE__ ) . '/CMB2/init.php' ) ) {
	require_once dirname( __FILE__ ) . '/CMB2/init.php';
}


add_action( 'cmb2_admin_init', 'status201_register_repeatable_group_field_metabox' );
/**
 * Hook in and add a metabox to demonstrate repeatable grouped fields with a WYSIWYG
 */
function status201_register_repeatable_group_field_metabox() {
	$prefix = 'status201_group_';

	/**
	 * Repeatable Field Groups
	 */
	$cmb_group = new_cmb2_box( array(
		'id'           => $prefix . 'metabox',
		'title'        => __( 'Content accordeon', 'cmb2' ),
		'object_types' => array( 'page', ),
	) );

	// $group_field_id is the field id string, so in this case: $prefix . 'subcontent'
	$group_field_id = $cmb_group->add_field( array(
		'id'          => $prefix . 'subcontent',
		'type'        => 'group',
		'description' => __( 'Voeg subcontent (titel en tekstveld paren) toe', 'cmb2' ),
		'options'     => array(
			'group_title'   => __( 'Subcontent {#}', 'cmb2' ), // {#} gets replaced by row number
			'add_button'    => __( 'Nieuwe subcontent toevoegen', 'cmb2' ),
			'remove_button' => __( 'Verwijder', 'cmb2' ),
			'sortable'      => true, // beta
			// 'closed'     => true, // true to have the groups closed by default
		),
	) );

	/**
	 * Group fields works the same, except ids only need
	 * to be unique to the group. Prefix is not needed.
	 *
	 * The parent field's id needs to be passed as the first argument.
	 */
	$cmb_group->add_group_field( $group_field_id, array(
		'name'       => __( 'Titel', 'cmb2' ),
		'id'         => 'title',
		'type'       => 'text',
		// 'repeatable' => true, // Repeatable fields are supported w/in repeatable groups (for most types)
	) );

	$cmb_group->add_group_field( $group_field_id, array(
		'name'        => __( 'Content', 'cmb2' ),
		'description' => __( 'Vrije tekst', 'cmb2' ),
		'id'          => 'content',
		'type'    => 'wysiwyg',
		'options' => array( 'textarea_rows' => 5, ),
	) );


}

The example code to get the values in the frontend:
(Again, replace status201 with your own prefix)

					$entries = get_post_meta( get_the_ID(), 'status201_group_' . 'subcontent', true );
					foreach ( (array) $entries as $key => $entry ) {

						if ( isset( $entry['title'] ) )
							$title = esc_html( $entry['title'] );
						
						if ( isset( $entry['content'] ) )
							$content = $entry['content'];

						// Output the values
						if ( !empty($title) ) echo '<h2>'.$title.'</h2>';
						if ( !empty($content) ) echo wpauotp($content); // wpautop to have paragraph tags!
					}

We only have to change some code inside includes/cmb2.js (and minified into includes/cmb2.min.js).
Find this line (inside the if ( isEditor ) { check):

				newID = newID ? oldID.replace( 'zx'+ prevNum, 'zx'+ cmb.idNumber ) : '';

And replace it with this:

				newID = newID ? oldID.replace( '_'+ prevNum, '_'+ cmb.idNumber ) : '';

Further down, find this code:

				if ( typeof( tinyMCEPreInit.qtInit[ id ] ) === 'undefined' ) {
					var newQTS = jQuery.extend( {}, tinyMCEPreInit.qtInit[ old ] );
					for ( _prop in newQTS ) {
						if ( 'string' === typeof( newQTS[_prop] ) ) {
							newQTS[_prop] = newQTS[_prop].replace( new RegExp( old, 'g' ), id );
						}
					}
					tinyMCEPreInit.qtInit[ id ] = newQTS;
				}
				tinyMCE.init({
					id : tinyMCEPreInit.mceInit[ id ],
				});

And replace it with this:

				if ( typeof( tinyMCEPreInit.qtInit[ id ] ) === 'undefined' )
				{
					tinyMCEPreInit.qtInit[id] = $.extend( {}, tinyMCEPreInit.qtInit[ old ] );
					tinyMCEPreInit.qtInit[id].id = id;

					//Remove cloned toolbar
					$('#qt_'+id+'_toolbar').remove();

					// make the editor area visible
					$('#'+id).addClass('wp-editor-area').show();

					// initialize quicktags
					new QTags(id);
					QTags._buttonsInit();
				}
				switchEditors.go(id, tinyMCEPreInit.mceInit[id].mode);
				tinymce.init(tinyMCEPreInit.mceInit[id]);

Download the patched cmb2.js and cmb2.min.js. (for version 2.2.2.1)

Leave a Reply