Why does this Quick Edit checkbox save the value only when unchecked?

Why the headline_news meta data is deleted on the Edit Post screen, with a fix

The qedit_save_post() function stomps on headline_news because $_POST['headline_news'] is not set when using the post edit screen.

Since the custom fields editor is being used for headline_news and there is no custom meta box involved, we’ll let the built-in custom field editor handle the saving of the meta data and deliberately NOT fire the quick edit saving logic when using the Edit Post screen. E.g.:

// Handle saving of headline_news via Quick Edit. This code will not fire on the post edit screen.
// The post edit screen will handle the field via the custom field editor.
if ( isset( $_POST[ '_inline_edit' ] ) && wp_verify_nonce( $_POST[ '_inline_edit' ], 'inlineeditnonce' ) ) {
    if ( isset( $_POST['headline_news'] ) ) {   
        update_post_meta( $post_id, 'headline_news', 'yes' );
    } else {
        delete_post_meta( $post_id, 'headline_news' );
    }                   
}

The duplicated Headline news position checkbox and fix

Initially I was unable to reproduce the phenomenon where you were getting a duplicate Headline news position checkbox, but after further review, I noticed that the original code was not checking $column_name in the quick_edit_add() function. The quick_edit_custom_box action is called once for each custom column, so I presume that there are actually multiple custom columns being added to your post listings and this code was not part of the original question (the columns could be added via plugins or the theme). We can add a check for the appropriate column to ensure that the output is only rendered once for each column:

// Print checkbox in Quick Edit for each custom column.
add_action( 'quick_edit_custom_box', 'quick_edit_add', 10, 2 );
function quick_edit_add( $column_name, $post_type ) {
    // Handle the headline_news checkbox
    
    // Note the added check. This prevents the output from being
    // rendered for every custom column & allows us to handle each individual column.
    switch ( $column_name ) {
        
        case 'headline_news' :
            printf( '<input type="checkbox" name="headline_news" class="headline_news"> %s',
                    __( 'Headline news position', 'text-domain' )
            );
        break;
        
        // Example of how another column could be incorporated:
        //case 'another_column' :
            //printf( '<input type="checkbox" name="another_column" class="another_column"> %s',
            //      __( 'Another Column', 'text-domain' )
            //);
        //break;        
    }
}

The full working solution:

Here is the original code with the fix for the edit post screen mentioned above, the fix for the duplicated Headline news position checkbox, and a couple of minor tweaks mainly related to WordPress coding standards.

// Add column to posts listing
add_filter( 'manage_post_posts_columns', 'add_columns' );
function add_columns( $columns ) {
    // Add the Headline News custom column.
    $columns['headline_news'] = __( 'Headline news', 'text-domain' );
    
    // Perhaps add other custom columns too.
    // $columns['another_column'] = __( 'Another Column', 'text-domain' );
    
    return $columns;
}

// Echo contents of custom field in column
add_action( 'manage_posts_custom_column', 'columns_content', 10, 2 );
function columns_content( $column_name, $post_id ) {
    switch ( $column_name ) {
        
        case 'headline_news' :
            $headline_news = get_post_meta( $post_id, 'headline_news', true );
            echo esc_html( $headline_news );
        break;
    
        // Example of how another column could be incorporated:
        //case 'another_column' :
        //  $another_column = get_post_meta( $post_id, 'another_column', true );
        //  echo esc_html( $another_column );
        //break;
    }
}

// Print checkbox in Quick Edit for each custom column.
add_action( 'quick_edit_custom_box', 'quick_edit_add', 10, 2 );
function quick_edit_add( $column_name, $post_type ) {
    // Handle the headline_news checkbox
    
    // Note the added check. This prevents the output from being
    // rendered for every custom column & allows us to handle each individual column.
    switch ( $column_name ) {
        
        case 'headline_news' :
            printf( '<input type="checkbox" name="headline_news" class="headline_news"> %s',
                    __( 'Headline news position', 'text-domain' )
            );
        break;
        
        // Example of how another column could be incorporated:
        //case 'another_column' :
            //printf( '<input type="checkbox" name="another_column" class="another_column"> %s',
            //      __( 'Another Column', 'text-domain' )
            //);
        //break;        
    }
}

// Save checkbox value
add_action( 'save_post', 'qedit_save_post', 10, 2 );
function qedit_save_post( $post_id, $post ) {
    
    // pointless if $_POST is empty (this happens on bulk edit)
    if ( empty( $_POST ) ) {
        return $post_id;
    }
    
    // Ensure quick edit nonce is set.
    if ( empty( $_POST[ '_inline_edit' ] ) ) {
      return $post_id;
    }

    // Verify quick edit nonce
    if ( ! wp_verify_nonce( $_POST[ '_inline_edit' ], 'inlineeditnonce' ) ) {
        return $post_id;
    }

    // Don't save for autosave
    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
        return $post_id;
    }

    // dont save for revisions
    if ( isset( $post->post_type ) && 'revision' === $post->post_type ) {
        return $post_id;
    }

    // Handle saving of headline_news via Quick Edit. This code will not fire on the post edit screen.
    // The post edit screen will handle the field via the custom field editor.
    if ( isset( $_POST[ '_inline_edit' ] ) && wp_verify_nonce( $_POST[ '_inline_edit' ], 'inlineeditnonce' ) ) {
        if ( isset( $_POST['headline_news'] ) ) {   
            update_post_meta( $post_id, 'headline_news', 'yes' );
        } else {
            delete_post_meta( $post_id, 'headline_news' );
        }                   
    }
}

// JavaScript functions to set/update checkbox
add_action( 'admin_footer', 'quick_edit_javascript' );
function quick_edit_javascript() {
    global $current_screen;
    if ( 'post' !== $current_screen->post_type ) {
        return;
    } ?>
    <script type="text/javascript">
        function checked_headline_news( fieldValue ) {
            inlineEditPost.revert();
            jQuery( '.headline_news' ).attr( 'checked', 0 == fieldValue ? false : true );
        }
    </script><?php
}

add_filter( 'post_row_actions', 'expand_quick_edit_link', 10, 2 );
function expand_quick_edit_link( $actions, $post ) {
    global $current_screen;
    $data = get_post_meta( $post->ID, 'headline_news', true );
    $data = empty( $data ) ? 0 : 1;
    $actions['inline hide-if-no-js']  = '<a href="#" class="editinline"';
    $actions['inline hide-if-no-js'] .=    ' title="' . esc_attr( __( 'Edit this item inline', 'text-domain' ) ) . '"';
    $actions['inline hide-if-no-js'] .=    " onclick=\"checked_headline_news('{$data}')\" >";
    $actions['inline hide-if-no-js'] .=   __( 'Quick Edit', 'text-domain' );
    $actions['inline hide-if-no-js'] .= '</a>';

    return $actions;
}

Leave a Comment