所以我在练习后回到这里,实现了一些炼金术设置,这意味着所有输入都有如下名称name="_movies[3][title]"
其中3是循环中的迭代。
创建元框
// metaboxes should be registered on the add_meta_boxes hook
add_action(\'add_meta_boxes\', \'add_meta_boxes\' );
function add_meta_boxes() {
add_meta_box( \'repeatable_fields\', \'Top 10 Movie List\', \'repeatable_meta_box_display\', \'cpt_top_ten_list\', \'normal\', \'default\');
}
function repeatable_meta_box_display( $post ) {
$repeatable_fields = get_post_meta($post->ID, \'repeatable_fields\', true);
if ( empty( $repeatable_fields ) ){
$repeatable_fields[] = array (
\'image\' => \'\',
\'title\' => \'\',
\'playback_format\' => \'dvd\',
\'description\' => \'\' );
}
wp_nonce_field( \'hhs_repeatable_meta_box_nonce\', \'hhs_repeatable_meta_box_nonce\' );
?>
<table id="repeatable-fieldset-one" class="widefat fixed" cellspacing="0" style="width:100%;">
<thead>
<tr>
<th style="width:25px;" scope="col">Rank</th>
<th style="width:170px;" scope="col">Image</th>
<th width="145px" scope="col">Movie Title</th>
<th width="300px" scope="col">Movie Description</th>
<th width="8%" scope="col">Re-Order</th>
</tr>
</thead>
<tbody>
<?php
// set a variable so we can append it to each row
$i = 1;
foreach ( $repeatable_fields as $field ) { ?>
<tr class="single-movie-row ui-state-default">
<td>
<label for="_movies[<?php echo $i;?>][rank]">
<input name="_movies[<?php echo $i;?>][rank]" id="_movies[<?php echo $i;?>][rank]" class="movie_rank_number" disabled="disabled" type="text" value="# <?php echo $i;?>" />
</label>
</td>
<td>
<label for="_movies[<?php echo $i;?>][image]">
<input name="_movies[<?php echo $i;?>][image]" class="upload_image" id="_movies[<?php echo $i;?>][image]" type="text" size="36" value="<?php echo esc_attr( $field[\'image\'] );?>" />
<input class="upload_image_button" id="_movies[<?php echo $i;?>][upload_image_button]" type="button" value="Upload Image" />
</label>
</td>
<td>
<!-- title field -->
<textarea name="_movies[<?php echo $i;?>][title]" id="_movies[<?php echo $i;?>][title]" class="title_tinymce_editor"><?php echo esc_html( $field[\'title\'] );?></textarea>
<div class="playbackformat-holder">
<label for="_movies[<?php echo $i;?>][playback_format][dvd]">
<input type="radio" id="_movies[<?php echo $i;?>][playback_format][dvd]" name="_movies[<?php echo $i;?>][playback_format]" value="dvd" <?php checked( $field[\'playback_format\'], \'dvd\' ); ?> />DVD
</label>
<label for="_movies[<?php echo $i;?>][playback_format][bluray]">
<input type="radio" id="_movies[<?php echo $i;?>][playback_format][bluray]" name="_movies[<?php echo $i;?>][playback_format]" value="bluray" <?php checked( $field[\'playback_format\'], \'bluray\' ); ?> />Bluray
</label><br>
<label for="_movies[<?php echo $i;?>][playback_format][3d]">
<input type="radio" id="_movies[<?php echo $i;?>][playback_format][3d]" name="_movies[<?php echo $i;?>][playback_format]" value="3d" <?php checked( $field[\'playback_format\'], \'3d\' ); ?> />3d
</label><br />
</div>
</td>
<td>
<textarea id="_movies[<?php echo $i;?>][description]" name="_movies[<?php echo $i;?>][description]" class="movie_description_editor_hidden"><?php echo esc_html( $field[\'description\'] );?></textarea>
</td>
<td>
<a class="button remove-row" href="#">Remove Row</a><img src="<?php echo get_template_directory_uri() ?>/images/draggable-icon.png" alt="sortable icon" class="jQuerySortableIcon">
</td>
</tr>
<?php $i++; } ?>
<!-- empty hidden one for jQuery -->
<tr class="empty-row screen-reader-text single-movie-row">
<td>
<label for="_movies[%s][rank]">
<input name="_movies[%s][rank]" id="_movies[%s][rank]" class="movie_rank_number" disabled="disabled" type="text" value="" />
</label>
</td>
<td>
<label for="_movies[%s][image]">
<input name="_movies[%s][image]" class="upload_image" id="_movies[%s][image]" type="text" size="36" value="" />
<input class="upload_image_button" id="_movies[<?php echo $i;?>][upload_image_button]" type="button" value="Upload Image" />
</label>
</td>
<td>
<!-- title field -->
<textarea name="_movies[%s][title]" id="_movies[%s][title]" class="title_tinymce_editor"></textarea>
<div class="playbackformat-holder">
<label for="_movies[%s][playback_format][dvd]">
<input type="radio" id="_movies[%s][playback_format][dvd]" name="_movies[%s][playback_format]" value="dvd" <?php checked( \'dvd\', \'dvd\' ); ?> />DVD
</label>
<label for="_movies[%s][playback_format][bluray]">
<input type="radio" id="_movies[%s][playback_format][bluray]" name="_movies[%s][playback_format]" value="bluray" />Bluray
</label><br>
<label for="_movies[%s][playback_format][3d]">
<input type="radio" id="_movies[%s][playback_format][3d]" name="_movies[%s][playback_format]" value="3d" />3d
</label><br />
</div>
<!-- drop down or checkbox\'s with release formats -->
</td>
<td>
<textarea id="_movies[%s][description]" name="_movies[%s][description]" class="movie_description_editor_hidden"></textarea>
</td>
<td>
<a class="button remove-row" href="#">Remove Row</a><img src="<?php echo get_template_directory_uri() ?>/images/draggable-icon.png" alt="sortable icon" class="jQuerySortableIcon">
</td>
</tr>
</tbody>
</table>
<p id="add-row-p-holder"><a id="add-row" class="btn btn-small btn-success" href="#">Insert Another Row</a></p>
<?php
}
保存元现在相对容易,因为名称中的数组为我们设置了元:
add_action(\'save_post\', \'hhs_repeatable_meta_box_save\', 10, 2);
function hhs_repeatable_meta_box_save($post_id) {
if ( ! isset( $_POST[\'hhs_repeatable_meta_box_nonce\'] ) ||
!wp_verify_nonce( $_POST[\'hhs_repeatable_meta_box_nonce\'], \'hhs_repeatable_meta_box_nonce\' ) )
return;
if (defined(\'DOING_AUTOSAVE\') && DOING_AUTOSAVE)
return;
if (!current_user_can(\'edit_post\', $post_id))
return;
$clean = array();
if ( isset ( $_POST[\'_movies\'] ) && is_array( $_POST[\'_movies\'] ) ) :
foreach ( $_POST[\'_movies\'] as $i => $movie ){
// skip the hidden "to copy" div
if( $i == \'%s\' ){
continue;
}
$playback_formats = array ( \'dvd\', \'bluray\', \'3d\' );
$clean[] = array(
\'image\' => isset( $movie[\'image\'] ) ? sanitize_text_field( $movie[\'image\'] ) : null,
\'title\' => isset( $movie[\'title\'] ) ? sanitize_text_field( $movie[\'title\'] ) : null,
\'playback_format\' => isset( $movie[\'playback_format\'] ) && in_array( $movie[\'playback_format\'], $playback_formats ) ? $movie[\'playback_format\'] : null,
\'description\' => isset( $movie[\'description\'] ) ? sanitize_text_field( $movie[\'description\'] ) : null,
);
}
endif;
// save movie data
if ( ! empty( $clean ) ) {
update_post_meta( $post_id, \'repeatable_fields\', $clean );
} else
delete_post_meta( $post_id, \'repeatable_fields\' );
}
我会说,我遇到了我们在聊天中谈到的同一个问题。。。。在经历了这一切之后,我仍然在运行第二台和第三台“playback\\u格式”收音机,而不是晚间发布的时候,我几乎疯了。但最后,我注意到你正在用
<form>
要素我确信这就是问题所在,因为我一摆脱它,它就奏效了。
我建议你试着减少额外的<Form>
首先查看代码,看看这是否解决了问题。这可能是您的其余代码工作。如果不是,那么我很确定我的现在是。。。然而,我已经更改了一些名称和ID,因此这可能会影响依赖于此的其余工作。
最后,关于我是如何改变一切的,我需要修改你的添加行JS。这里进行了简化,因为我不想处理tinyMCE编辑器,所以我只留下文本区域用于测试目的。
使用Javascript复制行
/*********************** Add Row Button Click *****************************/
$( \'#add-row\' ).click(function() {
var rowCount = $(\'#repeatable-fieldset-one\').find(\'.single-movie-row\').not(\':last-child\').size();
var newRowCount = rowCount + 1;
var row = $( \'.empty-row.screen-reader-text\' ).clone(true);
// Loop through all inputs
row.find(\'input, textarea, label\').each(function(){
if ( !! $(this).attr(\'id\') )
$(this).attr(\'id\', $(this).attr(\'id\').replace(\'[%s]\', \'[\' + newRowCount + \']\') ); // Replace for
if ( !! $(this).attr(\'name\') )
$(this).attr(\'name\', $(this).attr(\'name\').replace(\'[%s]\', \'[\' + newRowCount + \']\') ); // Replace for
if ( !! $(this).attr(\'for\') )
$(this).attr(\'for\', $(this).attr(\'for\').replace(\'[%s]\', \'[\' + newRowCount + \']\') ); // Replace for
});
row.removeClass( \'empty-row screen-reader-text\' ).find(\'.movie_rank_number\').val(\'# \'+newRowCount);
row.insertBefore( \'.empty-row\' );
// if row count hits 10, hide the add row button
if ( newRowCount == 10 ) {
jQuery(\'#add-row\').fadeOut();
}
return false;
});