This document provides a reusable implementation to add dynamic form fields with support for multiple field types, including TinyMCE, in WordPress. The implementation includes functions for rendering, validating, and saving fields dynamically.
Code Implementation
Define the Fields
// Define the fields with additional types
function wbcom_get_business_info_fields() {
return [
'business_name' => [
'label' => 'Business Legal Name',
'type' => 'text',
'sanitize_callback' => 'sanitize_text_field',
],
'business_address' => [
'label' => 'Business Address',
'type' => 'textarea',
'sanitize_callback' => 'sanitize_textarea_field',
],
'contact_number' => [
'label' => 'Contact Number',
'type' => 'text',
'sanitize_callback' => 'sanitize_text_field',
],
'email_address' => [
'label' => 'Email Address',
'type' => 'email',
'sanitize_callback' => 'sanitize_email',
],
'business_type' => [
'label' => 'Business Type',
'type' => 'select',
'options' => [
'retail' => 'Retail',
'service' => 'Service',
'manufacturing' => 'Manufacturing',
],
'sanitize_callback' => 'sanitize_text_field',
],
'services_offered' => [
'label' => 'Services Offered',
'type' => 'checkbox',
'options' => [
'delivery' => 'Delivery',
'pickup' => 'Pickup',
'consultation' => 'Consultation',
],
'sanitize_callback' => 'wbcom_sanitize_array',
],
'preferred_contact_method' => [
'label' => 'Preferred Contact Method',
'type' => 'radio',
'options' => [
'phone' => 'Phone',
'email' => 'Email',
'in_person' => 'In Person',
],
'sanitize_callback' => 'sanitize_text_field',
],
'availability' => [
'label' => 'Availability Dates',
'type' => 'multiselect',
'options' => [
'mon' => 'Monday',
'tue' => 'Tuesday',
'wed' => 'Wednesday',
'thu' => 'Thursday',
'fri' => 'Friday',
],
'sanitize_callback' => 'wbcom_sanitize_array',
],
'start_date' => [
'label' => 'Start Date',
'type' => 'date',
'sanitize_callback' => 'sanitize_text_field',
],
'business_description' => [
'label' => 'Business Description',
'type' => 'tinymce',
'tinymce_toolbar' => 'basic',
'sanitize_callback' => 'wp_kses_post',
],
];
}
Sanitize Array Inputs
// Sanitize array inputs (for checkbox and multiselect fields)
function wbcom_sanitize_array($input) {
return array_map('sanitize_text_field', (array) $input);
}
Display the Fields Dynamically
// Display the fields dynamically
function wbcom_display_business_info_fields_in_contact() {
$post_id = get_the_ID();
$fields = wbcom_get_business_info_fields();
echo '<form method="post">';
wp_nonce_field('wbcom_save_business_info', 'wbcom_business_info_nonce');
foreach ($fields as $field_key => $field) {
$value = get_post_meta($post_id, $field_key, true);
echo '<p>';
echo '<label for="' . esc_attr($field_key) . '">' . esc_html($field['label']) . ':</label><br>';
// Generate the field based on its type
switch ($field['type']) {
case 'textarea':
echo '<textarea name="' . esc_attr($field_key) . '" id="' . esc_attr($field_key) . '">' . esc_textarea($value) . '</textarea>';
break;
case 'select':
echo '<select name="' . esc_attr($field_key) . '" id="' . esc_attr($field_key) . '">';
foreach ($field['options'] as $option_value => $option_label) {
echo '<option value="' . esc_attr($option_value) . '"' . selected($value, $option_value, false) . '>' . esc_html($option_label) . '</option>';
}
echo '</select>';
break;
case 'checkbox':
foreach ($field['options'] as $option_value => $option_label) {
$checked = is_array($value) && in_array($option_value, $value) ? 'checked' : '';
echo '<input type="checkbox" name="' . esc_attr($field_key) . '[]" value="' . esc_attr($option_value) . '" ' . $checked . '> ' . esc_html($option_label) . '<br>';
}
break;
case 'radio':
foreach ($field['options'] as $option_value => $option_label) {
echo '<input type="radio" name="' . esc_attr($field_key) . '" value="' . esc_attr($option_value) . '" ' . checked($value, $option_value, false) . '> ' . esc_html($option_label) . '<br>';
}
break;
case 'multiselect':
echo '<select name="' . esc_attr($field_key) . '[]" id="' . esc_attr($field_key) . '" multiple>';
foreach ($field['options'] as $option_value => $option_label) {
$selected = is_array($value) && in_array($option_value, $value) ? 'selected' : '';
echo '<option value="' . esc_attr($option_value) . '" ' . $selected . '>' . esc_html($option_label) . '</option>';
}
echo '</select>';
break;
case 'date':
echo '<input type="date" name="' . esc_attr($field_key) . '" id="' . esc_attr($field_key) . '" value="' . esc_attr($value) . '">';
break;
case 'tinymce':
$toolbar = $field['tinymce_toolbar'] === 'basic'
? 'bold italic underline | bullist numlist | link unlink'
: 'bold italic underline strikethrough | alignleft aligncenter alignright | bullist numlist | blockquote link unlink';
wp_editor($value, $field_key, [
'textarea_name' => $field_key,
'quicktags' => false,
'media_buttons' => false,
'teeny' => true,
'tinymce' => [
'toolbar1' => $toolbar,
'toolbar2' => '',
'menubar' => false,
],
]);
break;
default: // Default to text input
echo '<input type="' . esc_attr($field['type']) . '" name="' . esc_attr($field_key) . '" id="' . esc_attr($field_key) . '" value="' . esc_attr($value) . '">';
break;
}
echo '</p>';
}
echo '</form>';
}
add_action('business_profile_after_contact_info', 'wbcom_display_business_info_fields_in_contact');
Save the Fields Dynamically
// Save the fields dynamically
function wbcom_save_business_info_fields($post_id) {
if (!isset($_POST['wbcom_business_info_nonce']) || !wp_verify_nonce($_POST['wbcom_business_info_nonce'], 'wbcom_save_business_info')) {
return;
}
$fields = wbcom_get_business_info_fields();
foreach ($fields as $field_key => $field) {
if (isset($_POST[$field_key])) {
$sanitize_callback = $field['sanitize_callback'] ?? 'sanitize_text_field';
$value = $field['type'] === 'checkbox' || $field['type'] === 'multiselect'
? call_user_func('wbcom_sanitize_array', wp_unslash($_POST[$field_key]))
: call_user_func($sanitize_callback, wp_unslash($_POST[$field_key]));
update_post_meta($post_id, $field_key, $value);
}
}
}
add_action('save_post', 'wbcom_save_business_info_fields');
Features
-
Support for Field Types:
- Text, Textarea, Select, Checkbox, Radio, Multiselect, Date, Email, and TinyMCE.
-
Dynamic Rendering:
- Form fields are generated dynamically based on configuration.
-
Sanitization:
- Ensures all inputs are sanitized before saving to the database.
-
Easily Extendable:
- Add new fields by updating the
wbcom_get_business_info_fieldsfunction.
- Add new fields by updating the
Usage
- Add the code to your theme’s
functions.phpfile or a custom plugin. - Modify
wbcom_get_business_info_fieldsto define your desired fields. - Test on the front end to ensure fields are displayed, validated, and saved correctly.
