I am trying to create dynamic input fields for set of predefined labels in a custom widget for a theme I am working on. I want to achieve something like this:
CourseName FieldONE FieldTWO
-------------------------------------------------------------
Chemistry Sprint 2015 Summer 2015 ( - )
Spring 2016 Summer 2016 ( - )
( + )
-------------------------------------------------------------
Biology Sprint 2015 Summer 2015 ( - )
Fall 2015 Winter 2015 ( - )
Spring 2016 Summer 2016 ( - )
( + )
--------------------------------------------------------------
Math Fall 2015 Winter 2015 ( - )
( + )
--------------------------------------------------------------
Physics Fall 2015 Winter 2015 ( - )
( + )
--------------------------------------------------------------
where CourseName
is Chemistry , Biology, Math and Physics (only predefined labels, max of 4) and FieldONE
and FieldTWO
are dynamic inputs where I want to enter different terms for each course.
So if I click on ( + )
, two fields FieldOne
and FieldTWO
are created for that label. And if I click the ( - )
, both fields are deleted.
I tried to use this Gist which creates similar dynamic input as metabox, and so far I got this:
<?php
/*
Plugin Name: Dynamic Fields Widget
Description: Dynamic Fields
Version: 0.0
Author: Rain Man
*/
// Creating the widget
class dynamic_widget extends WP_Widget
{
public function __construct()
{
parent::__construct(
// Base ID of your widget
'dynamic_widget',
// Widget name will appear in UI
__('Dynamic Widget', 'dynamic_widget_domain'),
// Widget description
array('description' => __('Sample Dynamic Widget', 'dynamic_widget_domain'))
);
}
// widget
public function widget($args, $instance)
{
$title = apply_filters('widget_title', $instance['title']);
// This is where you run the code and display the output
echo __('Hello, World!', 'dynamic_widget_domain');
echo $args['after_widget'];
}
// form
public function form($instance)
{
if (isset($instance[ 'title' ])) {
$title = $instance[ 'title' ];
} else {
$title = __('New title', 'dynamic_widget_domain');
}
// Widget admin form
$repeatable_fields = array();
$courses = array(
'Chemistry' => array(
'coursecode' => 'Chemistry 2059',
'professor' => 'Dr. James Bond',
),
'Biology' => array(
'coursecode' => 'Biology 3029',
'professor' => 'Dr. James Bond',
),
'Math' => array(
'coursecode' => 'Math 2043',
'professor' => 'Dr. James Bond',
),
'Physics' => array(
'coursecode' => 'Physics 2075',
'professor' => 'Dr. James Bond',
)
);
?>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script type="text/javascript">
jQuery(document).ready(function( $ ){
$( '#add-row' ).on('click', function() {
var row = $( '.empty-row.screen-reader-text' ).clone(true);
row.removeClass( 'empty-row screen-reader-text' );
row.insertBefore( '#repeatable-fieldset-one tbody>tr:last' );
return false;
});
$( '.remove-row' ).on('click', function() {
$(this).parents('tr').remove();
return false;
});
});
</script>
<?php foreach ($courses as $course_key => $course_info) { ?>
<label><?php echo $course_info['coursecode']; ?></label>
<table id="repeatable-fieldset-one" width="100%">
<thead>
<tr>
<th width="40%">Fall Term</th>
<th width="40%">Winter Term</th>
<th width="8%"></th>
</tr>
</thead>
<tbody>
<?php
if ($repeatable_fields) :
foreach ($repeatable_fields as $field) {
?>
<tr>
<td><input type="text" class="widefat" name="name[]" value="<?php if ($field['name'] != '') {
echo esc_attr($field['name']);
} ?>" /></td>
<td>
</td>
<td><input type="text" class="widefat" name="url[]" value="<?php if ($field['url'] != '') {
echo esc_attr($field['url']);
} else {
echo '';
} ?>" /></td>
<td><a class="button remove-row" href="#">Remove</a></td>
<td><a id="add-row" class="button" href="#">Add</a></td>
</tr>
<?php
} else :
// show a blank one
?>
<tr>
<td><input type="text" class="widefat" name="name[]" /></td>
<td><input type="text" class="widefat" name="url[]" value="" /></td>
<td><a class="button remove-row" href="#">Remove</a></td>
<td><a id="add-row" class="button" href="#">Add</a></td>
</tr>
<?php endif; ?>
<? } ?>
<!-- empty hidden one for jQuery -->
<tr class="empty-row screen-reader-text">
<td><input type="text" class="widefat" name="name[]" /></td>
<td><input type="text" class="widefat" name="url[]" value="" /></td>
<td><a class="button remove-row" href="#">Remove</a></td>
<td><a id="add-row" class="button" href="#">Add</a></td>
</tr>
</tbody>
</table>
</p>
<?php
}
// update
public function update($new_instance, $old_instance)
{
$instance = array();
$instance['title'] = (!empty($new_instance['title'])) ? strip_tags($new_instance['title']) : '';
return $instance;
}
} // Class dynamic_widget ends here
// Register and load the widget
function wpb_load_widget()
{
register_widget('dynamic_widget');
}
add_action('widgets_init', 'wpb_load_widget');
and here is a screenshot:
there are a lot of problems right now, first the javascript "Add" button no longer works and I am not sure how to save the data to access later.
any idea how to make dynamic input fields for the labels? It does not have to be similar to the code from the gist I shared, but it would be best if we can get my modifications to work.
If you want to dynamically add elements, you should have a container where to place them. For instance, a <div id="container"> . Create new elements by means of document. createElement() , and use appendChild() to append each of them to the container.
Using WordPress Custom WidgetGo to the Appearance menu, and select Widgets. You should see a widget named Hostinger Sample Widget in the Available Widgets list. Next, drag the widget and drop it in the Sidebar section on the right side of the page. Save your changes and visit your website.
Adding Custom Widget in WordPress Classic Editor There will be a new widget called 'WPBeginner Widget' in the list of available widgets. You need to drag and drop this widget into your sidebar. Then, enter a title and click 'Save' to save your widget settings. Your new custom widget will now be live on your website.
Try this code, I tested it and it works. The js code needs to be inserted in footer not in widget, otherwise the click button will be executed twice.
In the function widget(),you will see the loop to display the input values.
<?php
/*
Plugin Name: Dynamic Fields Widget
Description: Dynamic Fields
Version: 0.0
Author: Rain Man
*/
// Creating the widget
class dynamic_widget extends WP_Widget
{
public $courses;
public function __construct()
{
parent::__construct(
// Base ID of your widget
'dynamic_widget',
// Widget name will appear in UI
__('Dynamic Widget', 'dynamic_widget_domain'),
// Widget description
array('description' => __('Sample Dynamic Widget', 'dynamic_widget_domain'))
);
$this->courses = array(
'Chemistry' => array(
'coursecode' => 'Chemistry 2059',
'professor' => 'Dr. James Bond',
),
'Biology' => array(
'coursecode' => 'Biology 3029',
'professor' => 'Dr. James Bond',
),
'Math' => array(
'coursecode' => 'Math 2043',
'professor' => 'Dr. James Bond',
),
'Physics' => array(
'coursecode' => 'Physics 2075',
'professor' => 'Dr. James Bond',
)
);
add_action( 'in_admin_footer',array( $this,'jsfooter'));
}
public function jsfooter() {
?>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script type="text/javascript">
jQuery(document).ready(function( $ ){
$(document ).off('click').on('click','div.open .add-row' , function() {
var row = $(this).closest('tr').clone(true);
row.find('input').each(function(){
$(this).val("");
});
// row.insertBefore( '#repeatable-fieldset-one tbody>tr:last' );
$(this).parents('tr').after(row);
return false;
});
$( document).on('click', 'div.open .remove-row',function() {
if ($(this).parents('tbody').find('tr').length >1) {
$(this).parents('tr').remove();
}
return false;
});
});
</script>
<?php
}
// widget
public function widget($args, $instance)
{
$title = apply_filters('widget_title', $instance['title']);
// This is where you run the code and display the output
foreach ($this->courses as $course_key => $course_info) {
echo $course_info['coursecode'] .'<br>';
foreach ($instance['repeat'][$course_key ]["fall"] as $k=>$field) {
echo 'Fall Term ' . $field .' / ';
echo 'Winter Term ' . $instance['repeat'][$course_key ]["winter"][$k] .'<br>';
}
}
echo $args['after_widget'];
}
// form
public function form($instance)
{
if (isset($instance[ 'title' ])) {
$title = $instance[ 'title' ];
} else {
$title = __('New title', 'dynamic_widget_domain');
}
// Widget admin form
$repeatable_fields= isset ( $instance['repeat'] ) ? $instance['repeat'] : array();
?>
<?php foreach ($this->courses as $course_key => $course_info) { ?>
<label><?php echo $course_info['coursecode']; ?></label>
<table id="repeatable-fieldset-one" width="100%">
<thead>
<tr>
<th width="40%">Fall Term</th>
<th width="40%">Winter Term</th>
<th width="8%"></th>
<th width="8%"></th>
</tr>
</thead>
<tbody>
<?php
if ($repeatable_fields[$course_key ]["fall"] || $repeatable_fields[$course_key ]["winter"]) :
foreach ($repeatable_fields[$course_key ]["fall"] as $k=>$field) {
?>
<tr>
<td><input type="text" class="widefat" name="<?php echo $this->get_field_name( 'repeat' )?>[<?php echo $course_key;?>][fall][]" value="<?php echo $field; ?>" /></td>
<td><input type="text" class="widefat" name="<?php echo $this->get_field_name( 'repeat' )?>[<?php echo $course_key;?>][winter][]" value="<?php echo $repeatable_fields[$course_key ]["winter"][$k]; ?>" /></td>
<td><a class="button remove-row" href="#">Remove</a></td>
<td><a class="button add-row" class="button" href="#">Add</a></td>
</tr>
<?php
} else :
// show a blank one
?>
<tr>
<td><input type="text" class="widefat" name="<?php echo $this->get_field_name( 'repeat' )?>[<?php echo $course_key;?>][fall][]" /></td>
<td><input type="text" class="widefat" name="<?php echo $this->get_field_name( 'repeat' )?>[<?php echo $course_key;?>][winter][]" value="" /></td>
<td><a class="button remove-row" href="#">Remove</a></td>
<td><a class="button add-row" class="button" href="#">Add</a></td>
</tr>
<?php endif; ?>
</tbody>
</table>
<?php } ?>
<!-- empty hidden one for jQuery -->
<?php
}
// update
public function update($new_instance, $old_instance)
{
$instance = array();
$instance['title'] = (!empty($new_instance['title'])) ? strip_tags($new_instance['title']) : '';
$instance['repeat'] = array();
if ( isset ( $new_instance['repeat'] ) )
{
foreach ( $new_instance['repeat'] as $k =>$value )
{
$instance['repeat'][$k] = $value;
}
}
return $instance;
}
} // Class dynamic_widget ends here
// Register and load the widget
function wpb_load_widget()
{
register_widget('dynamic_widget');
}
add_action('widgets_init', 'wpb_load_widget');
The data will be stored in $instance['repeat"] in an array like that (to understand how I made the loop)
array (size=4)
'Chemistry' =>
array (size=2)
'fall' =>
array (size=1)
0 => string 'AAA' (length=3)
'winter' =>
array (size=1)
0 => string 'BBBBBBB' (length=7)
'Biology' =>
array (size=2)
'fall' =>
array (size=2)
0 => string 'CCCCCC' (length=6)
1 => string 'EEEEEEE' (length=7)
'winter' =>
array (size=2)
0 => string 'DDDD' (length=4)
1 => string 'FFFFFFFF' (length=8)
'Math' =>
array (size=2)
'fall' =>
array (size=1)
0 => string 'GGGGGGG' (length=7)
'winter' =>
array (size=1)
0 => string 'HHHHHH' (length=6)
'Physics' =>
array (size=2)
'fall' =>
array (size=1)
0 => string 'IIIIIIIII' (length=9)
'winter' =>
array (size=1)
0 => string 'JJJJJJJJ' (length=8)
I think customising this plugin may serve the purpose: https://wordpress.org/plugins/advanced-custom-fields-table-field/installation/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With