Settings API – creating reusable form elements?

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