Ask your WordPress questions! Pay money and get answers fast! Comodo Trusted Site Seal
Official PayPal Seal

settings API: how to create a multicheckbox with blog categories? WordPress

Hi,

I need to create a callback function with a multi checkbox with all the web/blog categories as multi options.

for better understanding my add_settings_fields are:


add_settings_field(
'select_page',
'Select Blog Page', /
'journal_combo_select_page_callback',
'journal_theme_blog_2_col',
'blog_page_blog_2_col_section'

);

add_settings_field(
'limit_posts',
'Limit Posts',
'journal_limit_posts_callback',
'journal_theme_blog_2_col',
'blog_page_blog_2_col_section'
);

add_settings_field( // $id, $title, $callback, $page, $section, $args
'check_categories', // $id
'Choose Categories', // $title
'journal_check_cats_callback', // $callback -
'journal_theme_blog_2_col', // $page
'blog_page_blog_2_col_section' // $section
);



do i need to declare some kind of array in settings_field 'check_categories' to comunicate with the callback function?




function journal_check_cats_callback() {
$options = get_option('journal_theme_blog_2_col');

$pag = journal_theme_blog_2_col;
$_cats = get_terms( 'category' );

$html = '';
foreach ($_cats as $term) {
$checked = isset( $term->term_id ) ? $term->term_id : '0' ;
$html .= sprintf( '<input type="checkbox" id="%1$s[%2$s]" name="journal_theme_blog_2_col[]" value="%2$s"%3$s />', $pag, $term->term_id, checked( $checked, $options['check_categories'], false ) );
$html .= sprintf( '<label for="%1$s[%3$s]"> %2$s</label><br>', $pag, $term->name, $term->term_id );
}
$html .= sprintf( '<span class="description"> %s</label>', '' );

echo $html;
}


And i have also this for Validate the function (i don't have pretty sure this is correct):
function journal_theme_validate_blog_2_col( $input ) {

// Create our array for storing the validated options
$output = array();

// Loop through each of the incoming options
foreach( $input as $key => $value ) {

// Check to see if the current option has a value. If so, process it.
if( isset( $input[$key] ) ) {

// Strip all HTML and PHP tags and properly handle quoted strings
$output[$key] = strip_tags( stripslashes( $input[ $key ] ) );

} // end if

} // end foreach




// Return the array processing any additional functions filtered by this action
return apply_filters( 'journal_theme_validate_blog_2_col', $output, $input );

} // end journal_theme_validate_blog_2_col



I'm trying to put this code working, but it's not quiet right yet... at the moment when i click in the Save button (submit) the values are saved in the wp_options table.
For example:

in settings_section i have three settings_fields. One combo box (select_page), one input text fiel (limit_posts) and one multicheck box with blog categorys (check_categories) and bellow is the data saved in wp-options table:

> a:4:{s:11:"select_page";s:1:"4";s:11:"limit_posts";s:3:"100";i:0;s:2:"13";i:1;s:1:"7";}

and this is the correspondent array:

> Array ( [select_page] => 4 [limit_posts] => 100 [0] => 13 [1] => 7 )




Problems to solve:
1 - the checkboxes don't stay checked! And of course if i click on save again without checking new ones, the values in the options table are erased.

2 - i also realized that the ID "check_categories" isn't save into the serialized value... So i think this is a problem, because i don't know how to fecth only the array values from "check_categories"


Someone can give me some help?

p.s. the theme admin page that i'm working it's built thru this sandbox:
[[LINK href="https://github.com/tommcfarlin/WordPress-Settings-Sandbox"]]https://github.com/tommcfarlin/WordPress-Settings-Sandbox[[/LINK]]

Thanks,
nelson

Answers (4)

2012-07-26

Arnav Joy answers:

try this


<?php

function journal_check_cats_callback() {

$options = get_option('journal_theme_blog_2_col');



$pag = journal_theme_blog_2_col;

$_cats = get_terms( 'category' );



$html = '';

foreach ($_cats as $term) {

$checked = isset( $term->term_id ) ? $term->term_id : '0' ;

if(in_array($term->term_id, $options [0]))

$html .= sprintf( '<input type="checkbox" id="%1$s[%2$s]" name="journal_theme_blog_2_col[]" checked="checked" value="%2$s"%3$s />', $pag, $term->term_id, checked( $checked, $options['check_categories'], false ) );

else

$html .= sprintf( '<input type="checkbox" id="%1$s[%2$s]" name="journal_theme_blog_2_col[]" value="%2$s"%3$s />', $pag, $term->term_id, checked( $checked, $options['check_categories'], false ) );

$html .= sprintf( '<label for="%1$s[%3$s]"> %2$s</label><br>', $pag, $term->name, $term->term_id );

}

$html .= sprintf( '<span class="description"> %s</label>', '' );



echo $html;

?>


naires comments:

Hi Arnav,

Thanks for the reply. Your code didn't work. Still doesn't stay checked after Save.

I guess "my" code needs to be rebuild (the callback function, and maybe the add_settings_field. I'm working thru this sandbox, but in the sandbox there isn't a multicheckbox solution :(


Arnav Joy comments:

please have a look in this plugin

http://wordpress.org/extend/plugins/options-framework/

2012-07-26

Martin Pham answers:

I can help you create a menu-page (not using the sandbox). But the prize should be: $20
If you agree to this, please leave your email


naires comments:

Hi Martin,

Thanks for the reply. Is the theme admin page built with the latest settings API? I could use some of the free frameworks that exist, but i want something independent, for not be waiting upgrades when needed.

I pick this sandbox to learn. I liked the menus and tabs options. And of course to have some examples of fields types to work with, except the multi checkbox to select categories (or other args).


Martin Pham comments:

Please try this. I hope to help you!

function journal_check_cats_callback() {
$options = get_option('journal_theme_blog_2_col');
$pag = journal_theme_blog_2_col;
$_cats = get_terms( 'category' );
$html = '';
foreach ($_cats as $term) {
$checked = in_array($term->term_id, $options) ? 'checked="checked"' : '';
$html .= sprintf( '<input type="checkbox" id="%1$s[%2$s]" name="[journal_theme_blog_2_col][]" value="%2$s" %3$s />', $pag, $term->term_id, $checked );
$html .= sprintf( '<label for="%1$s[%3$s]"> %2$s</label><br>', $pag, $term->name, $term->term_id );
}
$html .= sprintf( '<span class="description"> %s</label>', '' );
echo $html;
}


naires comments:

Martin,

Thanks for the code. But unfortunately it keeps saving values in the database, but without showing the checkboxes values in wp-options checked :(


naires comments:

oh by the away, your code does this: If there is values already saved in wp-options, the checkboxes display as checked. But if i try to select another one or simple Save, all the data will be erase in the table and it's no possible do save a new one.

2012-07-27

Stephanie Leary answers:

I do this by writing a custom walker so I can change the name attribute to match the setting name i've registered. (At least until bug [[LINK href="http://core.trac.wordpress.org/ticket/16437"]]#16437[[/LINK]] gets fixed.) (Edited to clarify: I'm assuming here that you're still registering the three settings, as in your original example. This custom walker is the way to have your category selections stored along with all your other settings using the API.)

In the options form:


<ul class="categorychecklist">
<?php wp_category_checklist(0, 0, $options['categories'], false, new My_Walker_Category_Checklist, false); ?>
</ul>


And somewhere outside the form:


// custom walker so we can change the name attribute of the category checkboxes
// mostly a duplicate of Walker_Category_Checklist
class My_Walker_Category_Checklist extends Walker {
var $tree_type = 'category';
var $db_fields = array ('parent' => 'parent', 'id' => 'term_id');

function start_lvl(&$output, $depth, $args) {
$indent = str_repeat("\t", $depth);
$output .= "$indent<ul class='children'>\n";
}

function end_lvl(&$output, $depth, $args) {
$indent = str_repeat("\t", $depth);
$output .= "$indent</ul>\n";
}

function start_el(&$output, $category, $depth, $args) {
extract($args);
if ( empty($taxonomy) )
$taxonomy = 'category';

// This is the part that's changed from the original walker
$name = 'check_categories[categories]';

$class = in_array( $category->term_id, $popular_cats ) ? ' class="popular-category"' : '';
$output .= "\n<li id='{$taxonomy}-{$category->term_id}'$class>" . '<label class="selectit"><input value="' . $category->term_id . '" type="checkbox" name="'.$name.'[]" id="in-'.$taxonomy.'-' . $category->term_id . '"' . checked( in_array( $category->term_id, $selected_cats ), true, false ) . disabled( empty( $args['disabled'] ), false, false ) . ' /> ' . esc_html( apply_filters('the_category', $category->name )) . '</label>';
}

function end_el(&$output, $category, $depth, $args) {
$output .= "</li>\n";
}
}


... and in your plugin's CSS, this will make the checkbox list look like the one on the Edit screens:


ul.categorychecklist { height: 15em; width: 20em; overflow-y: scroll; border: 1px solid #dfdfdf; padding: 0 1em; background: #fff; border-radius: 4px; -moz-border-radius: 4px; -webkit-border-radius: 4px; }
ul.categorychecklist ul.children { margin-left: 1em; }


naires comments:

Hi Stephanie Leary,

Thank you for your reply. But what i want is a solution using the built in wordpress settings API. But still i will try your answer and i will tell later if it worked or not.

best,
nelson

2012-07-27

ewienermerl answers:

Omega Constellation Brushed Quartz - $224.00 : TITLE, SITE_TAGLINE