Settings API – creating reusable form elements?

I have a set of settings fields:

(...)
add_settings_field( 'Option1', 'Option 1', 'textarea', 'page1', 'plugin_options');  
add_settings_field( 'Option2', 'Option 2', 'textarea', 'page1', 'plugin_options'); 
add_settings_field( 'Option3', 'Option 3', 'text_input', 'page1', 'plugin_options');  
add_settings_field( 'Option4', 'Option 4', 'text_input', 'page1', 'plugin_options');
(...)   

All tutorials and Codex state that I have to create separate rendering functions for each settings field, but wouldn’t be it much easier to create just basic functions for all input fields like checkbox, radio button, textarea etc. and reuse them?

I believe it will work smoothly if I’ll be able to pass fields id to these functions, but I’m not sure how?

function textarea() {
    $options = get_option('my_settings');
    echo "<textarea id='[how to get ID?]' name="my_settings[[how to get ID?]">{$options['how to get ID?']}</textarea>";
}

1
1

You’re absolutely right that you can pass reusable form field markup to add_settings_field(). The trick is to define the data type for each setting, and then pass the same callback to each call to add_settings_field(). Within that callback, you simply add a switch that includes cases for each data type.

Here’s how I do it in Oenology:

First, I dynamically output all calls to add_settings_field():

<?php
/**
 * Call add_settings_field() for each Setting Field
 * 
 * Loop through each Theme option, and add a new 
 * setting field to the Theme Settings page for each 
 * setting.
 * 
 * @link    http://codex.wordpress.org/Function_Reference/add_settings_field    Codex Reference: add_settings_field()
 * 
 * @param   string      $settingid  Unique Settings API identifier; passed to the callback function
 * @param   string      $title      Title of the setting field
 * @param   callback    $callback   Name of the callback function in which setting field markup is output
 * @param   string      $pageid     Name of the Settings page to which to add the setting field; passed from add_settings_section()
 * @param   string      $sectionid  ID of the Settings page section to which to add the setting field; passed from add_settings_section()
 * @param   array       $args       Array of arguments to pass to the callback function
 */
foreach ( $option_parameters as $option ) {
    $optionname = $option['name'];
    $optiontitle = $option['title'];
    $optiontab = $option['tab'];
    $optionsection = $option['section'];
    $optiontype = $option['type'];
    if ( 'internal' != $optiontype && 'custom' != $optiontype ) {
        add_settings_field(
            // $settingid
            'oenology_setting_' . $optionname,
            // $title
            $optiontitle,
            // $callback
            'oenology_setting_callback',
            // $pageid
            'oenology_' . $optiontab . '_tab',
            // $sectionid
            'oenology_' . $optionsection . '_section',
            // $args
            $option
        );
    } if ( 'custom' == $optiontype ) {
        add_settings_field(
            // $settingid
            'oenology_setting_' . $optionname,
            // $title
            $optiontitle,
            //$callback
            'oenology_setting_' . $optionname,
            // $pageid
            'oenology_' . $optiontab . '_tab',
            // $sectionid
            'oenology_' . $optionsection . '_section'
        );
    }
}
?>

And here’s how I define oenology_setting_callback():

<?php
/**
 * Callback for get_settings_field()
 */
function oenology_setting_callback( $option ) {
    $oenology_options = oenology_get_options();
    $option_parameters = oenology_get_option_parameters();
    $optionname = $option['name'];
    $optiontitle = $option['title'];
    $optiondescription = $option['description'];
    $fieldtype = $option['type'];
    $fieldname="theme_oenology_options[" . $optionname . ']';

    // Output checkbox form field markup
    if ( 'checkbox' == $fieldtype ) {
        ?>
        <input type="checkbox" name="<?php echo $fieldname; ?>" <?php checked( $oenology_options[$optionname] ); ?> />
        <?php
    }
    // Output radio button form field markup
    else if ( 'radio' == $fieldtype ) {
        $valid_options = array();
        $valid_options = $option['valid_options'];
        foreach ( $valid_options as $valid_option ) {
            ?>
            <input type="radio" name="<?php echo $fieldname; ?>" <?php checked( $valid_option['name'] == $oenology_options[$optionname] ); ?> value="<?php echo $valid_option['name']; ?>" />
            <span>
            <?php echo $valid_option['title']; ?>
            <?php if ( $valid_option['description'] ) { ?>
                <span style="padding-left:5px;"><em><?php echo $valid_option['description']; ?></em></span>
            <?php } ?>
            </span>
            <br />
            <?php
        }
    }
    // Output select form field markup
    else if ( 'select' == $fieldtype ) {
        $valid_options = array();
        $valid_options = $option['valid_options'];
        ?>
        <select name="<?php echo $fieldname; ?>">
        <?php 
        foreach ( $valid_options as $valid_option ) {
            ?>
            <option <?php selected( $valid_option['name'] == $oenology_options[$optionname] ); ?> value="<?php echo $valid_option['name']; ?>"><?php echo $valid_option['title']; ?></option>
            <?php
        }
        ?>
        </select>
        <?php
    } 
    // Output text input form field markup
    else if ( 'text' == $fieldtype ) {
        ?>
        <input type="text" name="<?php echo $fieldname; ?>" value="<?php echo wp_filter_nohtml_kses( $oenology_options[$optionname] ); ?>" />
        <?php
    } 
    // Output the setting description
    ?>
    <span class="description"><?php echo $optiondescription; ?></span>
    <?php
}
?>

Note that I account for a “custom” type, so that I can output one-off markup for settings that might need it. These require individual callbacks.

Also, this code accounts for a tabbed settings page, which may be more complex than you need. It should be easy to make that bit static, though.

Leave a Comment