I'm trying to create a multiple custom user profile fields to allow our users adding more software skills in their profile page.
The problem I'm facing is it always saving only one meta for "skills"
and one meta for "skills_percent"
even if I added more inputs!
What should I do to save all of them when I adding more fields?
And how to display all of them as well in the front end!
here what I have done.
<table class="skills-table">
<tr>
<th><label for="skills"><?php _e("Skills"); ?></label></th>
<td>
<div class="multi-field-wrapper">
<button type="button" class="add-field">+</button>
<div class="multi-fields">
<div class="multi-field">
<input type="text" name="skills" id="skills" value="<?php echo esc_attr( get_the_author_meta( 'skills', $current_user->ID ) ); ?>" class="textbox" />
<input type="text" name="skills_percent" id="skills_percent" value="<?php echo esc_attr( get_the_author_meta( 'skills_percent', $current_user->ID ) ); ?>" class="textbox" /><br />
<button type="button" class="remove-field">-</button>
</div>
</div>
</div>
<span class="description"><?php _e("Please enter your programs or software in the first box and how many percent in the second box ."); ?></span>
</td>
</tr>
</table>
script for adding/removing
fields dynamically.
<script type="text/javascript">
jQuery(document).ready(function($) {
$('.multi-field-wrapper').each(function() {
var $wrapper = $('.multi-fields', this);
$(".add-field", $(this)).click(function(e) {
$('.multi-field:first-child', $wrapper).clone(true).appendTo($wrapper).find('input').val('').focus();
});
$('.multi-field .remove-field', $wrapper).click(function() {
if ($('.multi-field', $wrapper).length > 1)
$(this).parent('.multi-field').remove();
});
});
});
</script>
updating the user meta
if ( !empty( $_POST['skills'] ) )
update_user_meta( $current_user->ID, 'skills', esc_attr( $_POST['skills'] ) );
if ( !empty( $_POST['skills_percent'] ) )
update_user_meta( $current_user->ID, 'skills_percent', esc_attr( $_POST['skills_percent'] ) );
displaying the author meta in the front end
<dt class="j-s-m">Skills</dt><dd class="text-intro"><?php echo get_the_author_meta('skills', $curauth->ID); ?> <?php echo get_the_author_meta('skills_percent', $curauth->ID); ?></dd>
Update 1 as mrben522 answer
if ( !empty( $_POST['skills'] ) )
$skillArray = [];
if (is_array($_POST['skills'])) {
foreach ($_POST['skills'] as $skill) {
$skillArray[] = esc_attr($skill);
}
} else {
$skillArray[] = esc_attr($_POST['skills']);
}
update_user_meta( $current_user->ID, 'skills', $skillArray );
if ( !empty( $_POST['skills_percent'] ) )
$skills_percentArray = [];
if (is_array($_POST['skills_percent'])) {
foreach ($_POST['skills_percent'] as $skill_percent) {
$skills_percentArray[] = esc_attr($skill_percent);
}
} else {
$skills_percentArray[] = esc_attr($_POST['skills_percent']);
}
update_user_meta( $current_user->ID, 'skills_percent', $skills_percentArray );
but it return Array Array for skills and skills percent, also not saving the second div of "multi-field"
I'm trying to create a multiple custom user profile fields to allow our users adding more software skills in their profile page.
The problem I'm facing is it always saving only one meta for "skills"
and one meta for "skills_percent"
even if I added more inputs!
What should I do to save all of them when I adding more fields?
And how to display all of them as well in the front end!
here what I have done.
<table class="skills-table">
<tr>
<th><label for="skills"><?php _e("Skills"); ?></label></th>
<td>
<div class="multi-field-wrapper">
<button type="button" class="add-field">+</button>
<div class="multi-fields">
<div class="multi-field">
<input type="text" name="skills" id="skills" value="<?php echo esc_attr( get_the_author_meta( 'skills', $current_user->ID ) ); ?>" class="textbox" />
<input type="text" name="skills_percent" id="skills_percent" value="<?php echo esc_attr( get_the_author_meta( 'skills_percent', $current_user->ID ) ); ?>" class="textbox" /><br />
<button type="button" class="remove-field">-</button>
</div>
</div>
</div>
<span class="description"><?php _e("Please enter your programs or software in the first box and how many percent in the second box ."); ?></span>
</td>
</tr>
</table>
script for adding/removing
fields dynamically.
<script type="text/javascript">
jQuery(document).ready(function($) {
$('.multi-field-wrapper').each(function() {
var $wrapper = $('.multi-fields', this);
$(".add-field", $(this)).click(function(e) {
$('.multi-field:first-child', $wrapper).clone(true).appendTo($wrapper).find('input').val('').focus();
});
$('.multi-field .remove-field', $wrapper).click(function() {
if ($('.multi-field', $wrapper).length > 1)
$(this).parent('.multi-field').remove();
});
});
});
</script>
updating the user meta
if ( !empty( $_POST['skills'] ) )
update_user_meta( $current_user->ID, 'skills', esc_attr( $_POST['skills'] ) );
if ( !empty( $_POST['skills_percent'] ) )
update_user_meta( $current_user->ID, 'skills_percent', esc_attr( $_POST['skills_percent'] ) );
displaying the author meta in the front end
<dt class="j-s-m">Skills</dt><dd class="text-intro"><?php echo get_the_author_meta('skills', $curauth->ID); ?> <?php echo get_the_author_meta('skills_percent', $curauth->ID); ?></dd>
Update 1 as mrben522 answer
if ( !empty( $_POST['skills'] ) )
$skillArray = [];
if (is_array($_POST['skills'])) {
foreach ($_POST['skills'] as $skill) {
$skillArray[] = esc_attr($skill);
}
} else {
$skillArray[] = esc_attr($_POST['skills']);
}
update_user_meta( $current_user->ID, 'skills', $skillArray );
if ( !empty( $_POST['skills_percent'] ) )
$skills_percentArray = [];
if (is_array($_POST['skills_percent'])) {
foreach ($_POST['skills_percent'] as $skill_percent) {
$skills_percentArray[] = esc_attr($skill_percent);
}
} else {
$skills_percentArray[] = esc_attr($_POST['skills_percent']);
}
update_user_meta( $current_user->ID, 'skills_percent', $skills_percentArray );
but it return Array Array for skills and skills percent, also not saving the second div of "multi-field"
Add square brackets to input names to get PHP to interpret them as an array of data instead of overriding the value with each new input.
so your input will look like this:
<input type="text" name="skills[]" id="skills" value="<?php echo esc_attr( get_the_author_meta( 'skills', $current_user->ID ) ); ?>" class="textbox" />
<input type="text" name="skills_percent[]" id="skills_percent" value="<?php echo esc_attr( get_the_author_meta( 'skills_percent', $current_user->ID ) ); ?>" class="textbox" /><br />
And your sanitization will look like this (repeat the structure for skills_percent
):
if ( !empty( $_POST['skills'] ) )
$skillArray = [];
if (is_array($_POST['skills'])) {
foreach ($_POST['skills'] as $skill) {
if (!empty($skill)) {
$skillArray[] = esc_attr($skill);
}
}
} else {
$skillArray[] = esc_attr($_POST['skills']);
}
update_user_meta( $current_user->ID, 'skills', $skillArray );
EDIT: You could also use array_map
instead of a foreach loop.
$skillArray = array_map('esc_attr', $_POST['skills']);
EDIT 2: Here's basic structure for looping over your data for showing the inputs. I don't love this layout as it relies on the indices for the two arrays staying the same, but it should work.
<?php
$skills = get_the_author_meta( 'skills', $current_user->ID );
$skillPercents = get_the_author_meta( 'skills_percent', $current_user->ID );
if (is_array($skills) && is_array($skillPercents)) {
foreach ($skills as $index => $skill) {
?>
<div class="multi-field">
<input type="text" name="skills[]" id="skills_<?php echo $index; ?>" value="<?php echo esc_attr( $skill ); ?>" class="textbox" />
<input type="text" name="skills_percent[]" id="skills_percent_<?php echo $index; ?>" value="<?php echo esc_attr( $skillPercents[$index] ); ?>" class="textbox" /><br />
<button type="button" class="remove-field">-</button>
</div>
<?php
}
} else { ?>
<div class="multi-field">
<input type="text" name="skills[]" id="skills_0" value="<?php echo esc_attr( $skills ); ?>" class="textbox" />
<input type="text" name="skills_percent[]" id="skills_percent_0" value="<?php echo esc_attr( $skillPercents ); ?>" class="textbox" /><br />
<button type="button" class="remove-field">-</button>
</div>
<?php }
?>
You can rework this so each skill and percent was saved as it's own array in a 2d array to make it a bit more sturdy if you want.