How to wrap html around Settings API add_settings_section()

I am writing a plugin and I’m currently implementing my admin menu using the wordpress settins API. As always with API’s, it facilitates programming to a certain degree, but it seems like I have an issue:

I need to wrap custom html around those sections. For example I want to wrap my form elements around a fieldset or I want to position logical units into two columns using CSS(float: right, float:left). In order to do so, I need to pack these sections into a container.

Read More

This is the API function that echo’s the sections.

function do_settings_sections( $page ) {
        global $wp_settings_sections, $wp_settings_fields;

        if ( ! isset( $wp_settings_sections[$page] ) )
                return;

        foreach ( (array) $wp_settings_sections[$page] as $section ) {
                if ( $section['title'] )
                        echo "<h3>{$section['title']}</h3>n";

                if ( $section['callback'] )
                        call_user_func( $section['callback'], $section );

                if ( ! isset( $wp_settings_fields ) || !isset( $wp_settings_fields[$page] ) || !isset( $wp_settings_fields[$page][$section['id']] ) )
                        continue;
                //MY WRAPPING NEEDS TO START HERE
                echo '<table class="form-table">';
                do_settings_fields( $page, $section['id'] );
                echo '</table>';
                //AND END HERE!
        }
}

As far as I read the source correctly, there’s no way to wrap custom html around it (only before, with the add_settings_section( $id, $title, $callback, $page ) $callback parameter).

So how would you solve this problem? Should I just inject the appropriate containers into the the global $wp_settings_sections (With the ordinary hook I will write the div and then in the last field of each setting I can close the container with /div. But this is a very very ugly workaround and it find it repellent to say the least!

Should I abandon the idea of using the great settings API?

Related posts

2 comments

  1. I’ve just run across this same issue myself on a project I am currently working on.

    Basically, what I did was break my settings into groups so they can then be displayed as a separate section(s):

    <?php
    
    class MyPluginSettings
    {
    
        /**
         * Constructor.
         *
         * @return void
         * @access public
         */
        public function __construct()
        {
            add_action('admin_menu', array($this, 'myPluginSettingsMenu'));
        }
    
    
        /**
         * Register our admin settings menu/page.
         *
         * @return void
         * @access public
         */
        public function myPluginSettingsMenu()
        {
            add_options_page(
                __('My Plugin Settings', TXTDMN),
                __('My Plugin', TXTDMN),
                'manage_options',
                'my-plugin-settings',
                array($this, 'myPluginSettingsPage')
            );
    
            add_action('admin_init', array($this, 'registerMyPluginSettings'));
        }
    
    
        /**
         * Create the admin settings page.
         *
         * @return void
         * @access public
         */
        public function myPluginSettingsPage()
        {
    
            ?>
            <div class="wrap">
                <h2><?php _e('My Plugin Settings', TXTDMN); ?></h2>
                <hr>
                <p class="howto"><?php _e('<strong class="label">Ahem:</strong> Introductory text/message/warning, etc.', TXTDMN); ?></p>
    
                <form action="options.php" method="post">
    
                    <?php settings_fields('my-plugin-settings-group'); ?>
    
                    <!-- CUSTOM STYLABLE SECTION #1 -->
                    <div class="my-plugin-options section general">
                        <?php do_settings_sections('my-plugin-general-settings'); ?>
    
                    </div>
    
                    <!-- CUSTOM STYLABLE SECTION #2 -->
                    <div class="my-plugin-options section special">
                        <?php do_settings_sections('my-plugin-special-settings'); ?>
    
                    </div>
    
                    <!-- CUSTOM STYLABLE SECTION #3 -->
                    <div class="my-plugin-options section misc">
                        <?php do_settings_sections('my-plugin-miscellaneous-settings'); ?>
    
                    </div>
    
                </form>
            </div>
        <?php
    
        }
    
    
        /**
         * Register all of our sections.
         *
         * @return void
         * @access public
         */
        public function registerMyPluginSettings()
        {
            $this->myPluginGeneralSection();
            $this->myPluginSpecialSection();
            $this->myPluginMiscellaneousSection();
        }
    
    
        /**
         * My Plugin general options.
         *
         * @return void
         * @access public
         */
        private function myPluginGeneralSection()
        {
            ...
        }
    
    
        /**
         * My Plugin special options.
         *
         * @return void
         * @access public
         */
        private function myPluginSpecialSection()
        {
            ...
        }
    
    
        /**
         * My Plugin miscellaneous options.
         *
         * @return void
         * @access public
         */
        private function myPluginMiscellaneousSection()
        {
            ...
        }
    }
    

    Hope this helps and makes sense to you 🙂

    Good luck.

  2. What works for me for just css styling or js scripts is using admin_enqueue_scripts:

    function my_plugin_enqueue($hook) {
        if ( 'settings_page_my-plugin/my-plugin' != $hook ) {
            return;
        }
        wp_register_style( 'my_plugin_admin_css', plugin_dir_url( __FILE__ ) . 'css/my_style_admin.css', false, '1.0.0' );
            wp_enqueue_style( 'my_plugin_admin_css' );
    
    }
    add_action( 'admin_enqueue_scripts', 'my_plugin_enqueue' );
    

    And by using the if ('bla bla bla' != $hook) you simply return before any enqueueing if it’s not your plugin options page.

    $hook appears to be what gets sent to the callback in the add_action call, and I retrieved it’s value for this specific plugin options page simply with adding print_r($hook) to the plugin options page for one load and grabbed it out of the browser.

    A less hackish way to do that would be by writing out to a file with a function like:

    //For Testing
    function write_to_file($message){
            $handle = fopen("/Applications/MAMP/logs/some_file_name.txt", "a+");
            fwrite($handle, "nMessage:t " . $message);
            fclose($handle);
        }
    

    Which would be used:

    write_to_file($message);
    

    And you’d avoid the ugly messages about the header already having been written.

Comments are closed.