Adding Custom Menu Item & Settings Form at Tools Panel of BB 2.0

Custom Menu Item with Settings Form

Custom Menu Item with Settings Form

I already published this tutorial. But it will not work for BB 2.0 version. Because new mechanism is using there. One of the Beaver user asked me how he will add the custom link with his own settings form at Tools panel of BB 2.0. In this article I am showing the step by step instructions how you will do the custom menu item with shortcuts key and settings form.

I created a class and js file for this functionality. At first I am describing the PHP and JavaScript codes & later sharing the full codes with complete steps.

1. Adding Custom Menu Link with Shortcuts Key

Beaver Builder 2.0 have a filter fl_builder_main_menu for main menu items. So you can add custom menu item(s) as per your requirements. Shortcuts key option is a cool feature of BB 2.0. So you can easily navigate the content with your keyboard keys. For shortcuts there have another filter fl_builder_keyboard_shortcuts. Here is the code and see how I used these two filters

Adding Custom Menu Link with Shortcuts Key

//* Creating the new menu
add_filter( 'fl_builder_main_menu', 			__CLASS__ . '::probb_builder_main_menu' );
//* Adding shortcut key with this menu
add_filter( 'fl_builder_keyboard_shortcuts', 	__CLASS__ . '::probb_bb_main_menu_keyboard_shortcuts' );

/**
 * Adding new menu "Custom Link" under Tools main menu panel in builder
 */
static public function probb_builder_main_menu( $views )
{
	$key_shortcuts = FLBuilder::get_keyboard_shortcuts();

	$views['main']['items'][120] = array(
		'type' => 'separator',
	);

	//* 45 is the menu order number. You can change the menu position by editng this number
	$views['main']['items'][130] = array(
		'label' 	=> __( 'Custom Link', 'theme-prefix' ),
		'type' 		=> 'event',
		'eventName' => 'showCustomSettings',
		'accessory' => $key_shortcuts['showCustomSettings']
	);

	return $views;
}

/**
 * Creating the shortcut key "m" for menu "Custom Link"
 * When press the "m" key, settings form will appear
 */
static public function probb_bb_main_menu_keyboard_shortcuts( $data )
{
	//* showCustomSettings is the eventName of "Custom Link" menu item
	$data['showCustomSettings'] = 'm';

	return $data;
}

2. Registering Settings Form

FLBuilder class have a method register_settings_form. It is registering the new form. This method is taking two parameters: form id as string and fields as an array. This method is triggering via init hook.

Registering Settings Form

//* Registering the custom settings form
add_action( 'init', 					__CLASS__ . '::probb_load_custom_settings_form' );

/**
 * Registering custom settings form with tabs & fields
 *
 * @uses 	register_settings_form method of FLBuilder class
 *
 * @param 	form id 		String
 * @param 	form fields 	Array
 */
static public function probb_load_custom_settings_form()
{
	//* customform is the settings form ID. It is require to populate the submitted data and render into form
	FLBuilder::register_settings_form('customform', array(
		'title' => __( 'Form Title', 'theme-prefix' ),
		'tabs' => array(

			'general'  => array(
				'title'         => __( 'General', 'theme-prefix' ),
				'sections'      => array(
					'sec_1' => array(
						'title' => __('Secction 1 Title', 'theme-prefix'),
						'fields' => array(
							'textf' => array(
								'label' => __('Input Box', 'theme-prefix'),
								'type' 	=> 'text',
								'help' 	=> __('This is optional. It is tooltip.', 'theme-prefix')
							),

							'textareaf' => array(
								'label' => __('Textarea', 'theme-prefix'),
								'type' 	=> 'textarea',
								'rows' 	=> 5
							)
						)
					),

					'sec_2' => array(
						'title' => __('Secction 2 Title', 'theme-prefix'),
						'fields' => array(
							'selectf' => array(
								'label' => __('Select', 'theme-prefix'),
								'type' 	=> 'select',
								'default' => 'none',
								'options' => array(
									'none' => __('None', 'theme-prefix'),
									'val-1' => __('Option 1', 'theme-prefix'),
									'val-2' => __('Option 2', 'theme-prefix'),
									'val-3' => __('Option 3', 'theme-prefix')
								)
							),

							'mselectf' => array(
								'label' => __('Multi-Select', 'theme-prefix'),
								'type' 	=> 'select',
								'multi-select' => true,
								'size' => 3,
								'default' => 'none',
								'options' => array(
									'none' => __('None', 'theme-prefix'),
									'val-1' => __('Option 1', 'theme-prefix'),
									'val-2' => __('Option 2', 'theme-prefix'),
									'val-3' => __('Option 3', 'theme-prefix')
								)
							),

							'iconf' => array(
								'label' => __('Icon', 'theme-prefix'),
								'type' 	=> 'icon',
								'show_remove' => true
							)
						)
					)
				)
			),

			'style'  => array(
				'title'         => __( 'Style', 'theme-prefix' ),
				'sections'      => array(
					'sec_3' => array(
						'title' => __('Secction 3 Title', 'theme-prefix'),
						'fields' => array(
							'colorf' => array(
								'label' => __('Color', 'theme-prefix'),
								'type' 	=> 'color',
								'default' => 'eeeeee',
								'show_reset' => true
							),

							'videof' => array(
								'label' => __('Video', 'theme-prefix'),
								'type' 	=> 'video'
							)
						)
					),

					'sec_4' => array(
						'title' => __('Secction 4 Title', 'theme-prefix'),
						'fields' => array(
							'unitf' => array(
								'label' => __('Unit', 'theme-prefix'),
								'type' 	=> 'unit',
								'default' => '2',
								'description' => 'px'
							),

							'timef' => array(
								'label' => __('Time', 'theme-prefix'),
								'type' 	=> 'time'
							)
						)
					)
				)
			),

			'another_tab'  => array(
				'title'         => __( 'Another Tab', 'theme-prefix' ),
				'sections'      => array(
					'sec_5' => array(
						'title' => __('Secction 5 Title', 'theme-prefix'),
						'fields' => array()
					),

					'sec_6' => array(
						'title' => __('Secction 6 Title', 'theme-prefix'),
						'fields' => array()
					)
				)
			)

			/**
			 * and more
			 .
			 .
			 .
			 .
			 */
		)
	));
}

3. Rendering Settings Form

Above settings form is rendering by following JS scripts.

Rendering the Settings Form

FLBuilder.addHook('showCustomSettings', this.showCustomSettings.bind(this));

/**
 * Helper for render action
 */
showCustomSettings: function()
{
	CustomForm._customLinkClicked();
	FLBuilder.MainMenu.hide();
}

/**
 * Shows the custom settings form lightbox when the
 * custom link menu item is clicked.
 */
_customLinkClicked: function()
{
	FLBuilderSettingsForms.render( {
		id        : 'customform',
		className : 'fl-builder-customform-settings',
		settings  : FLBuilderConfig.customform
	}, function() {
		FLBuilder._layoutSettingsInitCSS();
	} );
},

_customLinkClicked method is rendering the settings form. Default or save data is passing to form by this PHP snippets.

add_filter( 'fl_builder_ui_js_config', function( $js_config ){
	$js_config['customform'] = self::probb_get_customform_settings();
	return $js_config; 
});


/**
 * Getting the settings data
 *
 * you will use this kind of snippet in your theme or plugin file.
 * See a demo:
 * $my_form_settings = Probb_BBMainMenu::probb_get_customform_settings();
 * echo "Input Box value: " . $my_form_settings->textf;
 * echo "Select Field Value" . $my_form_settings->selectf;
 */
static public function probb_get_customform_settings()
{
	if ( null === self::$customform_settings ) {
		$settings = get_option( '_fl_builder_customform_settings' );
		$defaults = FLBuilderModel::get_settings_form_defaults( 'customform' );

		if ( ! $settings ) {
			$settings = array();
		}

		// Merge in defaults and cache settings
		self::$customform_settings = (object) array_merge( (array) $defaults, (array) $settings );
		self::$customform_settings = FLBuilderModel::merge_nested_form_defaults( 'general', 'preset', self::$customform_settings );
	}

	return self::$customform_settings;
}

probb_get_customform_settings method is retrieving the submitted form’s data as an object from WordPress options database table. Options key name is _fl_builder_customform_settings and data is storing as serialized way. See the attached screen

4. Saving the Submitted Data

User inputted data is saving into WordPress options table with the Builder AJAX API. AJAX action is adding by FLBuilderAJAX::add_action() method into the queue with wp hook. This method is accepting three parameters: action name, method and arguments

//* Adds callable AJAX actions
add_action( 'wp', 						__CLASS__ . '::probb_add_ajax_actions', 9 );
/**
 * Adds callable AJAX actions.
 */
static public function probb_add_ajax_actions()
{
	FLBuilderAJAX::add_action( 'save_customform_settings', 'Probb_BBMainMenu::probb_save_customform_settings', array( 'settings' ) );
}

save_customform_settings action name is stated into JS script. See the _saveButtonClicked function into the custom.form.actions.js file. probb_save_customform_settings method of Probb_BBMainMenu class is saving the user’s submitted data as serialized data into WordPress options table. Options name is _fl_builder_customform_settings.

Saving the data

/**
 * Saving the form data
 */
static public function probb_save_customform_settings( $settings = array() )
{
	$old_settings = self::probb_get_customform_settings();
	$new_settings = (object) array_merge( (array) $old_settings, (array) $settings );

	FLBuilderModel::delete_asset_cache_for_all_posts();
	self::$customform_settings = null;

	update_option( '_fl_builder_customform_settings', $new_settings );

	return self::probb_get_customform_settings();
}

5. Displaying Data at Front-end

You will write the following PHP scripts into your theme’s or plugin’s file.

Echo the data

$my_settings = Probb_BBMainMenu::get_customform_settings(); //* data is returnign as object
//* echo the input field data. This case field name is textf
echo $my_settings->textf;

For security purposes You will sanitize the data as per your requirement.


Complete code with Full Instructions

Create one class file “class-probb-bb-main-menu.php” and save into theme’s classes folder. You will create this folder if you have not one yet.

Class File

 'separator',
		);

		//* 45 is the menu order number. You can change the menu position by editng this number
		$views['main']['items'][130] = array(
			'label' 	=> __( 'Custom Link', 'theme-prefix' ),
			'type' 		=> 'event',
			'eventName' => 'showCustomSettings',
			'accessory' => $key_shortcuts['showCustomSettings']
		);

		return $views;
	}

	/**
	 * Creating the shortcut key "m" for menu "Custom Link"
	 */
	static public function probb_bb_main_menu_keyboard_shortcuts( $data )
	{
		//* showCustomSettings is the eventName of "Custom Link" menu item
		$data['showCustomSettings'] = 'm';

		return $data;
	}

	/**
	 * Getting the settings data
	 *
	 * you will use this kind of snippet in your theme or plugin file.
	 * See a demo:
	 * $my_form_settings = Probb_BBMainMenu::probb_get_customform_settings();
	 * echo "Input Box value: " . $my_form_settings->textf;
	 * echo "Select Field Value" . $my_form_settings->selectf;
	 *
	 * @uses 	FLBuilderModel::get_settings_form_defaults()
	 * @uses 	FLBuilderModel::merge_nested_form_defaults()
	 */
	static public function probb_get_customform_settings()
	{
		if ( null === self::$customform_settings ) {
			$settings = get_option( '_fl_builder_customform_settings' );
			$defaults = FLBuilderModel::get_settings_form_defaults( 'customform' );

			if ( ! $settings ) {
				$settings = array();
			}

			// Merge in defaults and cache settings
			self::$customform_settings = (object) array_merge( (array) $defaults, (array) $settings );
			self::$customform_settings = FLBuilderModel::merge_nested_form_defaults( 'general', 'preset', self::$customform_settings );
		}

		return self::$customform_settings;
	}

	/**
	 * Registering custom settings form with tabs & fields
	 *
	 * @uses 	register_settings_form method of FLBuilder class
	 *
	 * @param 	form id 		String
	 * @param 	form fields 	Array
	 */
	static public function probb_load_custom_settings_form()
	{
		//* customform is the settings form ID. It is require to populate the submitted data and render into form
		FLBuilder::register_settings_form('customform', array(
			'title' => __( 'Form Title', 'theme-prefix' ),
			'tabs' => array(

				'general'  => array(
					'title'         => __( 'General', 'theme-prefix' ),
					'sections'      => array(
						'sec_1' => array(
							'title' => __('Secction 1 Title', 'theme-prefix'),
							'fields' => array(
								'textf' => array(
									'label' => __('Input Box', 'theme-prefix'),
									'type' 	=> 'text',
									'help' 	=> __('This is optional. It is tooltip.', 'theme-prefix')
								),

								'textareaf' => array(
									'label' => __('Textarea', 'theme-prefix'),
									'type' 	=> 'textarea',
									'rows' 	=> 5
								)
							)
						),

						'sec_2' => array(
							'title' => __('Secction 2 Title', 'theme-prefix'),
							'fields' => array(
								'selectf' => array(
									'label' => __('Select', 'theme-prefix'),
									'type' 	=> 'select',
									'default' => 'none',
									'options' => array(
										'none' => __('None', 'theme-prefix'),
										'val-1' => __('Option 1', 'theme-prefix'),
										'val-2' => __('Option 2', 'theme-prefix'),
										'val-3' => __('Option 3', 'theme-prefix')
									)
								),

								'mselectf' => array(
									'label' => __('Multi-Select', 'theme-prefix'),
									'type' 	=> 'select',
									'multi-select' => true,
									'size' => 3,
									'default' => 'none',
									'options' => array(
										'none' => __('None', 'theme-prefix'),
										'val-1' => __('Option 1', 'theme-prefix'),
										'val-2' => __('Option 2', 'theme-prefix'),
										'val-3' => __('Option 3', 'theme-prefix')
									)
								),

								'iconf' => array(
									'label' => __('Icon', 'theme-prefix'),
									'type' 	=> 'icon',
									'show_remove' => true
								)
							)
						)
					)
				),

				'style'  => array(
					'title'         => __( 'Style', 'theme-prefix' ),
					'sections'      => array(
						'sec_3' => array(
							'title' => __('Secction 3 Title', 'theme-prefix'),
							'fields' => array(
								'colorf' => array(
									'label' => __('Color', 'theme-prefix'),
									'type' 	=> 'color',
									'default' => 'eeeeee',
									'show_reset' => true
								),

								'videof' => array(
									'label' => __('Video', 'theme-prefix'),
									'type' 	=> 'video'
								)
							)
						),

						'sec_4' => array(
							'title' => __('Secction 4 Title', 'theme-prefix'),
							'fields' => array(
								'unitf' => array(
									'label' => __('Unit', 'theme-prefix'),
									'type' 	=> 'unit',
									'default' => '2',
									'description' => 'px'
								),

								'timef' => array(
									'label' => __('Time', 'theme-prefix'),
									'type' 	=> 'time'
								)
							)
						)
					)
				),

				'another_tab'  => array(
					'title'         => __( 'Another Tab', 'theme-prefix' ),
					'sections'      => array(
						'sec_5' => array(
							'title' => __('Secction 5 Title', 'theme-prefix'),
							'fields' => array()
						),

						'sec_6' => array(
							'title' => __('Secction 6 Title', 'theme-prefix'),
							'fields' => array()
						)
					)
				)

				/**
				 * and more
				 .
				 .
				 .
				 .
				 */
			)
		));
	}

	/**
	 * Enqueue scripts
	 */
	static public function probb_enqueue_scripts()
	{
		if ( FLBuilderModel::is_builder_active() ) {
			wp_enqueue_script('custom-form-actions', get_stylesheet_directory_uri() . '/js/custom.form.actions.js', array(), time(), true );
		}
	}

	/**
	 * Adds callable AJAX actions.
	 */
	static public function probb_add_ajax_actions()
	{
		FLBuilderAJAX::add_action( 'save_customform_settings', 'Probb_BBMainMenu::probb_save_customform_settings', array( 'settings' ) );
	}

	/**
	 * Saving the form data
	 */
	static public function probb_save_customform_settings( $settings = array() )
	{
		$old_settings = self::probb_get_customform_settings();
		$new_settings = (object) array_merge( (array) $old_settings, (array) $settings );

		FLBuilderModel::delete_asset_cache_for_all_posts();
		self::$customform_settings = null;

		update_option( '_fl_builder_customform_settings', $new_settings );

		return self::probb_get_customform_settings();
	}
}

Probb_BBMainMenu::init();

Create a JS file “custom.form.actions.js” and save into theme’s js (case-sensitive) file. You will create this folder if you have not one yet.

JS File

(function($, FLBuilder) {
	CustomForm = {
		init: function()
		{
			FLBuilder.addHook( 'didSaveCustomFormSettingsComplete', this.updateOnSaveCustomFormSettings.bind( this ) );
			FLBuilder.addHook('showCustomSettings', this.showCustomSettings.bind(this));
			CustomForm._bindEvents();
		},

		_bindEvents: function() {
			$('body').delegate('.fl-builder-customform-settings .fl-builder-settings-save', 'click', CustomForm._saveButtonClicked);
			$('body').delegate('.fl-builder-customform-settings .fl-builder-settings-cancel', 'click', FLBuilder._cancelLayoutSettingsClicked);
		},

		/**
		 * Shows the custom settings form lightbox when the
		 * custom link menu item is clicked.
		 */
		_customLinkClicked: function()
		{
			FLBuilderSettingsForms.render( {
				id        : 'customform',
				className : 'fl-builder-customform-settings',
				settings  : FLBuilderConfig.customform
			}, function() {
				FLBuilder._layoutSettingsInitCSS();
			} );
		},

		/**
		 * Saves the form data when the save button is clicked.
		 */
		_saveButtonClicked: function()
		{
			var form     = $(this).closest('.fl-builder-settings'),
				valid    = form.validate().form(),
				settings = FLBuilder._getSettings( form );

			if(valid) {

				FLBuilder.showAjaxLoader();
				FLBuilder._layoutSettingsCSSCache = null;

				FLBuilder.ajax({
					action: 'save_customform_settings',
					settings: settings
				}, CustomForm._saveCustomFormSettingsComplete);

				FLBuilder._lightbox.close();
			}
		},

		_saveCustomFormSettingsComplete: function( response )
		{
			FLBuilderConfig.customform = JSON.parse( response );

			FLBuilder.triggerHook( 'didSaveCustomFormSettingsComplete', FLBuilderConfig.customform );
			FLBuilder._updateLayout();
		},

		updateOnSaveCustomFormSettings: function( e, settings )
		{
			this.customform = settings;
		},

		showCustomSettings: function()
		{
			CustomForm._customLinkClicked();
			FLBuilder.MainMenu.hide();
		}
	}

	$(function(){ CustomForm.init(); });

})(jQuery, FLBuilder)

Now open the functions.php file of your theme and add this single line of code there

Include the class file

require_once 'classes/class-probb-bb-main-menu.php';

All are done. You will enable the page builder and click on “Custom Link” menu item or press “m” key. Settings form will appear. Fill up the form and click on “Save” button.

Posted in