How to Loop Plugin Option Field Set?

Problem/Background

Currently, I’m creating a plugin for a client that will enable them to mark and modify predetermined Google Map polygons (displayed on the site) in the dashboard.

I want to let the user mark a polygon as important, set a custom color, opacity, and info window text — all of which I have been able to do so far. The problem is that these field sets need to exist for all 180-ish polygons. With the WP settings API I can create and save the fields, but it would be ridiculous to create 500+ callbacks to cover each specific field. So for the past couple of days I’ve been trying to loop through the field set a specific number of times and appending a variable number.

Read More

Current Code

Here’s the current option field registration for one set of polygons (as stored in a class):

<?php
public function page_init() {
    //[. . . ]
    add_settings_section(
        'rangers_txs',
        'Texas Senate District Options',
        array($this, 'print_txs_info'),
        'rangers_txs_option'
    );
    register_setting(
        'rangers_txs',
        'rangers_txs_option',
        array($this, 'ranger_txs_sanitize')
    );

    $i=1;
    while($i <= 31) {
        add_settings_field(
            'rangers_txs_checkbox_'.$i, //id
            'Is District '.$i.' important?', //Title
            array( $this, 'rangers_txs_check_callback_'.$i), //callback
            'rangers_txs_option', //page
            'rangers_txs', //section
            array('field' => 'txs_checkbox')
        );
        add_settings_field(
            'rangers_txs_colorpicker_'.$i, //id
            'District Color', //Title
            array( $this, 'rangers_txs_color_callback_'.$i ), //callback
            'rangers_txs_option', //page
            'rangers_txs', //section
            array('field' => 'txs_colorpicker')
        );
        add_settings_field(
            'rangers_txs_opacity_'.$i, //id
            'How important is it?', //Title
            array( $this, 'rangers_txs_opacity_callback_'.$i ), //callback
            //array($this, 'rangers_txs_input_array'),
            //'rangers_txs_opacity_callback_'.$i, //callback
            'rangers_txs_option', //page
            'rangers_txs', //section
            array('field' => 'txs_opacity')
        );
        add_settings_field(
            'rangers_txs_info_'.$i, //id
            'District Information', //Title
            array( $this, 'rangers_txs_info_callback_'.$i ), //callback
            'rangers_txs_option', //page
            'rangers_txs', //section
            array('field' => 'txs_info')
        );

        $i++;
    }

}
?>

And here’s one set of callbacks, which I’ve tested and work properly:

<?php
public function colorpicker_init() {
    echo '<script type="text/javascript">
            jQuery(document).ready(function($) {
              $(".tr-color-picker").wpColorPicker();
            });
          </script>';
}
public function rangers_txs_check_callback_1() {
    printf(
        '<input type="checkbox" id="rangers_txs_checkbox_1" name="rangers_txs_option[rangers_txs_checkbox_1]" %1$s />
        <label for="rangers_txs_option[rangers_txs_checkbox_1]">Yep, it's important.', 
        checked( isset($this->txsoptions['rangers_txs_checkbox_1']), true, false)
    );
}
public function rangers_txs_color_callback_1() {
    $this->colorpicker_init();

    $color = $this->txsoptions['rangers_txs_colorpicker_1'] != '' ? sanitize_text_field($this->txsoptions['rangers_txs_colorpicker_1']) : '#0A64A4';
    printf(
        '<input type="text" name="rangers_txs_option[%1$s]" id="%1$s" class="tr-color-picker" data-default-color="#0A64A4" value="'.$color.'" />',
        'rangers_txs_colorpicker_1'
    );
}
public function rangers_txs_opacity_callback_1() {
    print '<p><em>On a scale of 1-10 (determines opacity of district, default: 5).</em></p>';
    printf(
        '<input type="text" id="rangers_txs_opacity_1" name="rangers_txs_option[rangers_txs_opacity_1]" value="%s" />', 
        isset( $this->txsoptions['rangers_txs_opacity_1'] ) ? esc_attr( $this->txsoptions['rangers_txs_opacity_1']) : '' 
    );
}
public function rangers_txs_info_callback_1() {
    isset($this->txsoptions['rangers_txs_info_1']) ? $content = $this->txsoptions['rangers_txs_info_1'] : $content = '';

    echo '<textarea id="rangers_txs_info_1" name="rangers_txs_option[rangers_txs_info_1]" rows="6" cols="50">'.$content.'</textarea>';
}
?>

Question

As you can see, I have a check box, a color picker, an opacity input, and a text area. I want the entire set to be looped for each polygon. I attempted to run the fields in one callback, but it simply lumped all of the same options together (i.e., 31 check boxes then 31 color pickers, etc.). I have also tried setting the callbacks outside of the class and looping a while around the function set, but using the $i variable in the function name returned errors, as did appending it before calling and when calling the functions.

I would greatly appreciate any suggestions that could help me achieve the result of looping field sets.

Related posts

1 comment

  1. I figured it out after a little work.

    To start, I ended up using a single callback: array($this, 'txs_loop_callbacks') using the same add_settings_field registration above. Then I altered the final argument in the field resgistration, making each unique to that specific field: array('field' => 'txs_opacity_'.$i).

    Then in the loop callback I stored each field’s HTML in a anonymous function defined as a variable. Like so:

    $txs_checkbox = function($num) {
        $is_checked = checked( isset($this->txsoptions['rangers_txs_checkbox_'.$num]), true, false);
        printf(
           '<input type="checkbox" class="is-important-'.$num.'" id="rangers_txs_checkbox_'.$i.'" name="rangers_txs_option[rangers_txs_checkbox_'.$num.']" %1$s />
            <label for="rangers_txs_option[rangers_txs_checkbox_'.$num.']">District '.$num.' is important</label><br /><br />', 
            $is_checked
        );
    };
    

    I defined this type of variable for each field type (i.e., $txs_checkbox, $txs_colorpicker, and on).

    After that, I called the anonymous functions inside a loop with a check to display only one kind of field per set.

    $n=1;
    while($n <= 31) {
        switch($args['field']):
            case('txs_checkbox_'.$n):
                $txs_checkbox($n);
                break;
    
            case('txs_colorpicker_'.$n):
                $txs_colorpicker($n);
                break;
    
            case('txs_opacity_'.$n):
                $txs_opacity($n);
                break;
    
            case('txs_info_'.$n):
                $txs_info($n);
                break;
        endswitch;
    
        $n++;
    }
    

    With those elements all together, I was able to achieve the result of repeating field sets.

Comments are closed.