Dynamic Form Fields for Business Profiles

Get Started

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

  1. Support for Field Types:

    • Text, Textarea, Select, Checkbox, Radio, Multiselect, Date, Email, and TinyMCE.
  2. Dynamic Rendering:

    • Form fields are generated dynamically based on configuration.
  3. Sanitization:

    • Ensures all inputs are sanitized before saving to the database.
  4. Easily Extendable:

    • Add new fields by updating the wbcom_get_business_info_fields function.

Usage

  1. Add the code to your theme’s functions.php file or a custom plugin.
  2. Modify wbcom_get_business_info_fields to define your desired fields.
  3. Test on the front end to ensure fields are displayed, validated, and saved correctly.
Last updated: November 19, 2024