I am at my first Settings API application and I hit a snag.

In a submenu page, I need to generate a number of fields (say color picker) for each of the values retrieved from another setting.

To be more precise, I created in another menu page a list of category checkboxes:

function bcio_fp_special_cats_display(){
$options = (array)get_option('bcio_options');
$categories = bcio_get_categories();

echo '<ul>';

foreach($categories as $category){
    $selected = ( isset( $options['fp_sp_category_'.$category->cat_ID] ) ) ? $options['fp_sp_category_'.$category->cat_ID] : '';    

    if($selected){  
        echo '<li><input type="checkbox" value="'.$category->cat_ID.'" name="bcio_options[fp_sp_category_'.$category->cat_ID.']" checked/>'.$category->name.'</li>';

    } else {
        echo '<li><input type="checkbox" value="'.$category->cat_ID.'" name="bcio_options[fp_sp_category_'.$category->cat_ID.']"/>'.$category->name.'</li>';            
    }       

}

echo '</ul>';}

In my second options page, I use the option values to generate the appropriate fields in another settings section:

function bcio_special_section_settings_display(){
echo "These settings fields are generated based on your selection of Special Front Page Categories";
$options = (array)get_option('bcio_options');
$categories = bcio_get_categories();

foreach($categories as $category){
    $selected = ( isset( $options['fp_sp_category_'.$category->cat_ID] ) ) ? $options['fp_sp_category_'.$category->cat_ID] : '';    
    $cat_id = $category->cat_ID;    
    if($selected){  
    add_settings_field( 
        'bcio_special_cat_'.$category->cat_ID,                  
        'Special Section:<br />'.$category->name,           
        'bcio_special_section_display("'.$cat_id.'")',      
        'business-cover-special-sections', 
        'bcio_special_sections_options'                 
    );


    }           
}}
//The field itself 
function bcio_special_section_display($cat_id){

        $special_options = (array)get_option('bcio_special_options');
        $color =  ( isset( $special_options['color'] ) ) ? $special_options['color'] : '';
        echo '<input type="text" name="bcio_options[color]" value="' . $color . '" class="bc-color-field" >';   
    }

This successfully generates the appropriate number of fields, applies the name of the category in the field label, but when I try to use the callback it messes up as the parameter $cat_id I pass in the field callback doesn’t quite work as I thought it would.

Warning: call_user_func() expects parameter 1 to be a valid callback, function ‘bcio_special_section_display(“12285”)’ not found or invalid function name in /nas/wp/www/cluster-2598/businesscover/wp-admin/includes/template.php on line 1237

I tried poking it in a few ways, but no luck and I really need to figure out a way to store options in association with category IDs without hardcoding the IDs themselves.

Getting this to work the right way with the Settings API or some non-plugin solution is paramount. I have a version based on ACF by Elliot Condon but would rather not make the theme dependent on a 3rd party plugin. The settings in these fields would define LESS vars, logos and so on for the site’s special sections. Any hints in the right direction would be much appreciated.

1 Answer
1

This issue is now resolved. I am posting the solution, in case someone else finds it useful.

I have modified my callback for adding the checkbox list of categories so that the selected categories are saved in an array instead of separate options. It will make it much easier to find said special category and matching it with queried_object in the front end.

function bcio_fp_special_cats_display(){
$options = (array)get_option('bcio_options');
$categories = bcio_get_categories();

echo '<ul>';

foreach($categories as $category){
    $selected = ( isset( $options['fp_sp_category'] ) ) ? $options['fp_sp_category'] : '';  

    if(in_array($category->cat_ID, $selected)){ 
        echo '<li><input type="checkbox" value="'.$category->cat_ID.'" name="bcio_options[fp_sp_category][]" checked/>'.$category->name.'</li>';

    } else {
        echo '<li><input type="checkbox" value="'.$category->cat_ID.'" name="bcio_options[fp_sp_category][]"/>'.$category->name.'</li>';            
    }       

}

echo '</ul>';


}

Based on the values contained in this new array (category ids), I then generate the setting fields, with the category ID as an argument to the field:

function bcio_special_section_settings_display(){
echo "These settings fields are generated based on your selection of Special Front Page Categories";
$options = (array)get_option('bcio_options');
$selected = ( isset( $options['fp_sp_category'] ) ) ? $options['fp_sp_category'] : '';  

      if($selected){    
      foreach($selected as $cat_id){
        add_settings_field( 
             'section_'.$cat_id,                    
             'Special Section:<br />'.get_cat_name( $cat_id ),          
             'bcio_special_section_display',        
             'business-cover-special-sections', 
             'bcio_special_sections_options', 
             $cat_id                
      );  
      }             
}
}

I then used the argument to give my field a unique ID, and to save the color option as color_$mycatid.

function bcio_special_section_display($args){
$special_options = (array)get_option('bcio_special_options');
$color =  ( isset( $special_options['color_'.$args] ) ) ? $special_options['color_'.$args] : '';
echo '<input type="text" id="color-'.$args.'" name="bcio_special_options[color_'.$args.']" value="' . $color . '" class="bc-color-field" >';                                    
}

I have tested the solution with per-category color fields. The colors are saved correctly and, if set, display as previously configured.

I hope someone else finds the solution helpful. If I discover any problems, I will post an update to this thread.

Happy coding!

Tags:

Leave a Reply

Your email address will not be published. Required fields are marked *