4

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.

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.

1 Answer 1

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.