How can I add a new column to quick edit and put a custom field in it? I read this question but one of the links lead to an error 404. I need a new column for my custom meta key, "summary
" and post types, "post
" and "episode
".
2 Answers
There are a few steps to create the custom quick edit box and custom column
- create a custom meta key (assumed that you have 1 already)
- add custom admin column title and data (assumed that you want to shows the custom meta key in the column, if not, you may also modify a bit of the logic to accomplish the same effect because the principal is the same)
- add custom quick edit box
- add save logic
- load script to modify original inline-edit-post function in order to support custom meta value
- prepare the script file
This example is going to add a quick edit input box in post type Page
. The following code is proved to work by putting in functions.php .
1. create a custom meta key (assumed that you have 1 already)
I have prepared a custom meta key remark
for post type page
2. add custom admin column title and data
for custom post type, you may use
Add column title
- For specific Screen ID manage_{$screen->id}_columns
- Specificially for Page manage_pages_columns
- Specificially for generic (default Post or custom post type) manage_posts_custom_column or for specific post type manage_{$post->post_type}_posts_custom_column to add column data
Add column content
- Generic (default Post or custom post type) manage_posts_columns with custom post type checking using post type argument or for specific post type manage_{$post_type}_posts_columns to add column title
The following is an example for post type Page as well as custom post type + default Post
as an example for multiple post types setup.
// add custom column title for custom meta value
add_filter('manage_edit-page_columns', 'ws365150_add_custom_columns_title' );
function ws365150_add_custom_columns_title( $columns ) {
$columns['page_remark'] = 'Remark'; // you may use __() later on for translation support
return $columns;
}
// add custom column data with custom meta value
add_action('manage_pages_custom_column', 'ws365150_add_custom_column_data', 10, 2 );
function ws365150_add_custom_column_data( $column_name, $post_id ) {
switch ( $column_name ) {
case 'page_remark':
echo get_post_meta( $post_id, 'remark', true );
break;
default:
break;
}
}
The following is an example for custom post type episode
+ default Post
with meta key summary
// add custom column title for custom meta value
// 'manage_pages_columns' or 'manage_edit-post_columns' both works
add_filter('manage_posts_columns', 'ws365150_add_custom_columns_title_pt', 10, 2 );
function ws365150_add_custom_columns_title_pt( $columns, $post_type ) {
switch ( $post_type ) {
case 'post':
case 'episode':
$columns['ws365150_summary'] = 'Summary'; // you may use __() later on for translation support
break;
default:
break;
}
return $columns;
}
// add custom column data with custom meta value for custom post types
add_action('manage_posts_custom_column', 'ws365150_add_custom_column_data_pt', 10, 2 );
function ws365150_add_custom_column_data_pt( $column_name, $post_id ) {
switch ( $column_name ) {
case 'ws365150_summary': // specified for this column assigned in the column title
echo get_post_meta( $post_id, 'summary', true );
break;
default:
break;
}
}
3. add custom quick edit box
// for page
add_action( 'quick_edit_custom_box', 'ws365150_custom_edit_box', 10, 3 );
function ws365150_custom_edit_box( $column_name, $post_type, $taxonomy ) {
global $post;
switch ( $post_type ) {
case 'page':
if( $column_name === 'page_remark' ): // same column title as defined in previous step
?>
<?php // echo get_post_meta( $post->ID, 'remark', true ); ?>
<fieldset class="inline-edit-col-right" id="#edit-">
<div class="inline-edit-col">
<label>
<span class="title">Remark</span>
<span class="input-text-wrap"><input type="text" name="remark" class="inline-edit-menu-order-input" value=""></span>
</label>
</div>
</fieldset>
<?php
endif;
// echo 'custom page field';
break;
default:
break;
}
}
// for Post + custom post type
add_action( 'quick_edit_custom_box', 'ws365150_custom_edit_box_pt', 10, 3 );
function ws365150_custom_edit_box_pt( $column_name, $post_type, $taxonomy ) {
global $post;
switch ( $post_type ) {
case 'post':
case 'episode':
if( $column_name === 'ws365150_summary' ): // same column title as defined in previous step
?>
<?php // echo get_post_meta( $post->ID, 'remark', true ); ?>
<fieldset class="inline-edit-col-right" id="#edit-">
<div class="inline-edit-col">
<label>
<span class="title">Summary</span>
<span class="input-text-wrap"><input type="text" name="summary" class="inline-edit-menu-order-input" value=""></span>
</label>
</div>
</fieldset>
<?php
endif;
// echo 'custom page field';
break;
default:
break;
}
}
4. add save logic
add_action( 'save_post', 'ws365150_update_custom_quickedit_box' );
function ws365150_update_custom_quickedit_box() {
// any checking logic here, skip and keep it simple for simple illustration purpose (nonce, existing of $_POST['remark'], ajax save and so on
// remark in Page
if( isset( $_POST ) && isset( $_POST['remark'] ) ) { // where remark is defined in the <input name="remark">
update_post_meta($_POST['post_ID'], 'remark', $_POST['remark']);
}
// summary in Post, custom post type
if( isset( $_POST ) && isset( $_POST['summary'] ) ) { // where summary is defined in the <input name="summary">
update_post_meta($_POST['post_ID'], 'summary', $_POST['summary']);
}
// for debugging purpose in inspector, not necessary, enable this will break the saving but could see the ajax return
// wp_send_json_success( array(
// 'message' => 'Save test!',
// 'post_data' => $_POST,
// ) );
return; // finish the function call
}
5. load script to modify original inline-edit-post function
add_action( 'admin_enqueue_scripts', function( $page ) {
// add page checking logic, this is a simple one, you may test post type and so on...
if ( 'edit.php' != $page ) {
return;
}
wp_enqueue_script( 'custom-quickedit-box', get_stylesheet_directory_uri() . '/ws365150_custom_quickedit_box.js', array( 'jquery', 'inline-edit-post' ) );
});
6. prepare the script file (ws365150_custom_quickedit_box.js, when test the above code, put in the theme folder)
( function( $, wp ) {
// clone from original function in inline-post-edit.js for override
// actually no need to create an alias object, however, create an alias could be a note and mark of override without forgetting for later maintenance
window.customInlineEditPost = window.inlineEditPost;
// function override: add custom meta value, the base is copied from the source
customInlineEditPost.edit = function(id) {
// console.log( 'custom edit' );
var t = this, fields, editRow, rowData, status, pageOpt, pageLevel, nextPage, pageLoop = true, nextLevel, f, val, pw;
t.revert();
if ( typeof(id) === 'object' ) {
id = t.getId(id);
}
fields = ['post_title', 'post_name', 'post_author', '_status', 'jj', 'mm', 'aa', 'hh', 'mn', 'ss', 'post_password', 'post_format', 'menu_order', 'page_template'];
if ( t.type === 'page' ) {
fields.push('post_parent');
}
// Add the new edit row with an extra blank row underneath to maintain zebra striping.
editRow = $('#inline-edit').clone(true);
$( 'td', editRow ).attr( 'colspan', $( 'th:visible, td:visible', '.widefat:first thead' ).length );
$(t.what+id).removeClass('is-expanded').hide().after(editRow).after('<tr class="hidden"></tr>');
// Populate fields in the quick edit window.
rowData = $('#inline_'+id);
if ( !$(':input[name="post_author"] option[value="' + $('.post_author', rowData).text() + '"]', editRow).val() ) {
// The post author no longer has edit capabilities, so we need to add them to the list of authors.
$(':input[name="post_author"]', editRow).prepend('<option value="' + $('.post_author', rowData).text() + '">' + $('#' + t.type + '-' + id + ' .author').text() + '</option>');
}
if ( $( ':input[name="post_author"] option', editRow ).length === 1 ) {
$('label.inline-edit-author', editRow).hide();
}
// populate custom meta value
if ( $( ':input[name="remark"]', editRow ).length === 1 ) {
$( ':input[name="remark"]', editRow ).val( $('#post-' + id + ' .page_remark').text() );
}
if ( $( ':input[name="summary"]', editRow ).length === 1 ) {
$( ':input[name="summary"]', editRow ).val( $('#post-' + id + ' .ws365150_summary').text() );
}
for ( f = 0; f < fields.length; f++ ) {
val = $('.'+fields[f], rowData);
/**
* Replaces the image for a Twemoji(Twitter emoji) with it's alternate text.
*
* @returns Alternate text from the image.
*/
val.find( 'img' ).replaceWith( function() { return this.alt; } );
val = val.text();
$(':input[name="' + fields[f] + '"]', editRow).val( val );
}
if ( $( '.comment_status', rowData ).text() === 'open' ) {
$( 'input[name="comment_status"]', editRow ).prop( 'checked', true );
}
if ( $( '.ping_status', rowData ).text() === 'open' ) {
$( 'input[name="ping_status"]', editRow ).prop( 'checked', true );
}
if ( $( '.sticky', rowData ).text() === 'sticky' ) {
$( 'input[name="sticky"]', editRow ).prop( 'checked', true );
}
/**
* Creates the select boxes for the categories.
*/
$('.post_category', rowData).each(function(){
var taxname,
term_ids = $(this).text();
if ( term_ids ) {
taxname = $(this).attr('id').replace('_'+id, '');
$('ul.'+taxname+'-checklist :checkbox', editRow).val(term_ids.split(','));
}
});
/**
* Gets all the taxonomies for live auto-fill suggestions when typing the name
* of a tag.
*/
$('.tags_input', rowData).each(function(){
var terms = $(this),
taxname = $(this).attr('id').replace('_' + id, ''),
textarea = $('textarea.tax_input_' + taxname, editRow),
comma = inlineEditL10n.comma;
terms.find( 'img' ).replaceWith( function() { return this.alt; } );
terms = terms.text();
if ( terms ) {
if ( ',' !== comma ) {
terms = terms.replace(/,/g, comma);
}
textarea.val(terms);
}
textarea.wpTagsSuggest();
});
// Handle the post status.
status = $('._status', rowData).text();
if ( 'future' !== status ) {
$('select[name="_status"] option[value="future"]', editRow).remove();
}
pw = $( '.inline-edit-password-input' ).prop( 'disabled', false );
if ( 'private' === status ) {
$('input[name="keep_private"]', editRow).prop('checked', true);
pw.val( '' ).prop( 'disabled', true );
}
// Remove the current page and children from the parent dropdown.
pageOpt = $('select[name="post_parent"] option[value="' + id + '"]', editRow);
if ( pageOpt.length > 0 ) {
pageLevel = pageOpt[0].className.split('-')[1];
nextPage = pageOpt;
while ( pageLoop ) {
nextPage = nextPage.next('option');
if ( nextPage.length === 0 ) {
break;
}
nextLevel = nextPage[0].className.split('-')[1];
if ( nextLevel <= pageLevel ) {
pageLoop = false;
} else {
nextPage.remove();
nextPage = pageOpt;
}
}
pageOpt.remove();
}
$(editRow).attr('id', 'edit-'+id).addClass('inline-editor').show();
$('.ptitle', editRow).focus();
return false;
};
})( jQuery, window.wp );
The above is for quick edit using quick_edit_custom_box
hook, and you may need to take care of bulk edit also. You may explore more by reading and using bulk_edit_custom_box
.
-
Great! Could you edit the example for the post types
post
andepisode
and the custom meta keysummary
? Sorry, I do not like fiddling with the functions.php file, I could accidentally wreck WordPress. I have to know that there is a 100% chance the code will function.– GustoMay 4, 2020 at 22:12 -
I have added additional example code for
post
,episode
withsummary
meta field with additional notes on column title and checking example when save. You may modify and add additional checking based on the content you needed. May 10, 2020 at 10:06 -
Wait a second, this code is not working and is just making my "All Pages" edit page blank.– GustoMay 12, 2020 at 20:47
-
The code is updated, please change
add_filter('manage_posts_columns', 'ws365150_add_custom_columns_title_pt' );
toadd_filter('manage_posts_columns', 'ws365150_add_custom_columns_title_pt', 10, 2 );
Please don't worry to hurry tick the answer before testing it out. May 12, 2020 at 23:15 -
Hm, when testing the above code, the new summary input is added to the
post
andepisode
post type's quick edit menu, but after clicking "update", thesummary
parameter is empty. Even if thesummary
parameter was already met (without using quick edit), the quick edit input still makes the parameter empty.– GustoMay 13, 2020 at 21:17
i didn't rewrite full js in step 6 i added just
(function($){
lesson_orders={};
if($('.post_type_page').length && $('.post_type_page').val()=='resource'){
$('#the-list tr').each(function(){
id=$(this).find('.check-column input').val();
val=$(this).find('.lesson_order').text();
lesson_orders['edit-'+id]=val;
});
}
$(document).on('focus','.ptitle',function(){
id =$(this).closest('.inline-edit-row').attr('id');
$('#'+id+' input[name="lesson_order"]').val(lesson_orders[''+id]);
});
})(jQuery);