2

I am developing an application (plugin) where the user needs to enter any number of number of phrases in the settings page and these will be used by the plugin.

I have implemented this to capture the input values as follows:

register_setting('my_group', 'my_options', 'my_validate');

The settings page points to the input form as:

function my_options_page() {
  echo '<div class="wrap">';
    echo '<h2>'.esc_html( get_admin_page_title() ).'</h2>';
    echo '<h3>Setup / Settings</h3>';
    settings_errors();
    echo '<form action="options.php" method="post">';
      settings_fields("my_group");
      echo '<table class="form-table">';
        echo '<tr valign="top"><th colspan="2">Data Input</th></tr>';
        echo '<tr valign="top"><th scope="row">Phrase [1]</th><td><input name="my_options['phrases'][0]" value="" size="32" type="text"></td></tr>';
        echo '<tr valign="top"><th scope="row">Phrase [2]</th><td><input name="my_options['phrases'][1]" value="" size="32" type="text"></td></tr>';
        echo '<tr valign="top"><th scope="row">Phrase [3]</th><td><input name="my_options['phrases'][2]" value="" size="32" type="text"></td></tr>';
      echo '</table>';
    echo '</form>';
  echo '</div>';
}

This allows the user to enter 3 phrases. The data validation declared in register_settings is:

function my_validate($input){
  foreach ($input['phrases'] as $i => $phrase) {
    $output['phrase'][$i] = esc_html($phrase);
  }
  return $output;
}

I am aware that I can add as many input fields as I need into the form to extend this from the 3 inputs, however, I would like the user to be able to add any number of phrases which then will be processed when the form is submitted and will be stored to the $output['phrase'][] array.

Is there some way to implement a multi-input field that will take as many phrases as the user wants to enter?

Any ideas or suggestions how to approach this will be welcomed.

3
  • You mean like a button that when users click on the button, more input fields appear?
    – Sally CJ
    Commented Jul 25, 2018 at 11:43
  • Yes that would be perfect. Ideally there should be a way of removing values as well. However, this would only be one set of inputs on the form and once all the values have been added, this should submit along with any other input fields. I know this is a big ask but if anyone has any ideas they might help. @sally-cj
    – WPDavid
    Commented Jul 26, 2018 at 19:26
  • I've posted an answer. Check it out and let me know how it goes.
    – Sally CJ
    Commented Jul 27, 2018 at 8:50

1 Answer 1

2

Is there some way to implement a multi-input field that will take as many phrases as the user wants to enter?

Yes, there is — you can add an input field where the user will enter a number, which is the number of extra phrases he/she wants to add.

But I'd go with a JavaScript/jQuery solution, where we use a repeatable field script like this. Just try the demo and let me know if you need assistance in using the script/code.

And here's how I implemented that solution/script with your phrases field:

First, register and enqueue the script file. For example:

add_action( 'admin_menu', 'my_add_admin_menu' );
function my_add_admin_menu() {
    // I used `add_options_page()`, but you can use similar function. The point
    // is, we'd need the `$hook_suffix` variable.
    $hook_suffix = add_options_page( 'WPSE 309235', 'WPSE 309235', 'manage_options', 'wpse-309235', 'my_options_page' );

    // Registers and enqueues our repeatable field script. You shouldn't "hotlink"
    // to CodePen. Instead, save the file to my-repeatable-field.js and upload it
    // to your site, and then link to that file.
    add_action( 'load-' . $hook_suffix, function(){
        wp_register_script( 'my-repeatable-field', 'https://codepen.io/anon/pen/vaJaGZ.js', [ 'jquery' ], '20180727' );
        wp_enqueue_script( 'my-repeatable-field' );
    } );
}

Second, add/use the necessary HTML and class names.

This is a modified version of your my_options_page() function. The main changes are inside the table, including the opening <table> tag.

function my_options_page() {
  echo '<div class="wrap">';
    echo '<h2>'.esc_html( get_admin_page_title() ).'</h2>';
    echo '<h3>Setup / Settings</h3>';
    //settings_errors(); // In my case, this isn't necessary.
    echo '<form action="options.php" method="post">';
      settings_fields("my_group");
      echo '<table class="form-table repeatable-field">';
        $phrases_arr = my_options( 'phrases' );
        $count = count( $phrases_arr );

        echo '<tr valign="top"><th colspan="2">Data Input</th></tr>';
        // Displays 3 initial rows.
        $rows = max( $count, 3 );
        for ( $i = 0, $j = 1; $i < $rows; $i++, $j++ ) {
            $phrase_str = isset( $phrases_arr[ $i ] ) ? $phrases_arr[ $i ] : '';
            echo '<tr valign="top" class="repeatable-field-row">' .
                '<th scope="row">Phrase [<span class="repeatable-field-number">' . $j . '</span>]</th>' .
                '<td><input name="my_options[phrases][]" value="' . esc_attr( $phrase_str ) . '" size="32" type="text" class="repeatable-field-input">' .
                    '<span class="repeatable-field-buttons"></span></td>' .
            '</tr>';
        }

        $phrases_url = my_options( 'phrases_url' );
        echo '<tr valign="top">' .
            '<th>Phrases URL (*Non-repeatable* Field)</th>' .
            '<td><input type="text" name="my_options[phrases_url]" value="' . esc_attr( $phrases_url ) . '" class="regular-text" placeholder="URL"></td>' .
        '</tr>';
      echo '</table>';
      submit_button();
    echo '</form>';
  echo '</div>';
}

That's all for the script part. However,

In the modified my_options_page() function code, there are calls made to my_options(), which I created to retrieve the options from the database. Here's the code:

function my_options( $key = null ) {
    $options = wp_parse_args( get_option( 'my_options' ), [
        'phrases'     => [],
        'phrases_url' => '',
    ] );

    // Returns a single option.
    if ( $key ) {
        return isset( $options[ $key ] ) ? $options[ $key ] : null;
    }

    // Returns all the options.
    return $options;
}

I also modified the my_validate() function code:

function my_validate($input){
  $phrases_arr = [];

  foreach ($input['phrases'] as $phrase) {
    if ( $phrase = esc_html( $phrase ) ) {
      $phrases_arr[] = $phrase;
    }
  }

  $input['phrases'] = $phrases_arr;

  return $input;
}

The full code

..is available here.

0

Your Answer

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

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