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.
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.