i'm doing my first plugin and got stuck with linking a row-action to a new editing-site!

What i'm trying to do:

-> Manage User Meta on a special settings site. Add some fields for documents and other informations about this "customer"

I've started with the boilerplate plugin generator, setting up a high-level menu entry, get all the existing users in a separated list. Now i want to edit the user-meta from a single user on a special site

-> created a new file html-edit-usermeta-admin-display.php

using the following code in my file class-user-list-table.php

    protected function column_user_login( $item ) {     
    $admin_page_url =  admin_url( 'admin.php' );
        // row action to edit usermeta.
        $query_args_edit_usermeta = array(
            'page'      =>  wp_unslash( $_REQUEST['page'] ),
            'action'    => 'edit_usermeta',
            'user_id'   => absint( $item['ID']),
            '_wpnonce'  => wp_create_nonce( 'edit_usermeta_nonce' ),
        $edit_usermeta_link = esc_url( add_query_arg( $query_args_edit_usermeta, $admin_page_url ) );       
        $actions['edit_usermeta'] = '<a href="' . $edit_usermeta_link . '">' . __( 'edit Meta', $this->plugin_text_domain ) . '</a>';

    $row_value = '<strong>' . $item['user_login'] . '</strong>';
    return $row_value . $this->row_actions( $actions );

handling the row actions

public function handle_table_actions() {

// check for individual row actions
    $the_table_action = $this->current_action();
    if ( 'edit_usermeta' === $the_table_action ) {
        $nonce = wp_unslash( $_REQUEST['_wpnonce'] );
        // verify the nonce.
        if ( ! wp_verify_nonce( $nonce, 'edit_usermeta_nonce' ) ) {
        else {                    
            $this->page_edit_usermeta( absint( $_REQUEST['user_id']) );

how can i redirect to a new page to /views/html-edit-usermeta-admin-display.php, instead fo firing the function as an ajax call?


Some coffee let me come up with this! If anyone else run in this same situation, some thoughts from a beginner.

First step: Register a submenu on class-init.php

$this->loader->add_action('admin_menu', $plugin_admin, 'add_plugin_admin_submenu');

We need this as "anchor", otherwise we can't link on this page.

Second Step: Passing a "add_submenu_page" array as callback on class-admin.php

public function add_plugin_admin_submenu() {
    $page_hook = add_submenu_page( 
        null, //parent_slug or set null for hidden submenu
        __( 'Edit User', $this->plugin_text_domain ), //page title
        __( 'Editing User', $this->plugin_text_domain ), //menu title
        'manage_options', //capability
        'edit', //menu_slug,
        array( $this, 'load_user_edit_page' )


Final Step: place function "load_user_edit_page" on class-admin.php

    public function load_user_edit_page(){
    $request = _$REQUEST; // request-data eg. action, user_id
    include_once( 'views/html-edit-usermeta-admin-display.php');

On this step, we need to include our template from /views. Now you should have a hidden submenu you can link to.

Set a row-action on class-user-list-table.php linked to the registered submenu-page

protected function column_user_login( $item ) {     
    $admin_page_url =  admin_url( 'admin.php' );
    $query_args_edit_usermeta = array(
        'page'      =>  'edit_usermeta',
        'action'    => 'edit',
        'user_id'   => absint( $item['ID']),
    $edit_usermeta_link = esc_url( add_query_arg( $query_args_edit_usermeta, $admin_page_url ) );       
    $actions['edit_usermeta'] = '<a href="' . $edit_usermeta_link . '">' . __( 'Edit Meta', $this->plugin_text_domain ) . '</a>';

$row_value = '<strong>' . $item['user_login'] . '</strong>';
return $row_value . $this->row_actions( $actions );

thats it!

My personal thoughts on this -> Developing in WordPress is great, but i hate the lack of documentation to get things done correctly. The whole thing isn't what i was looking for, to me its more a "hack" instead of an intended solution. Why? Take a look at the top-level menu entry, now you have to deal with a missing active-state. I've tried a lot to get this problem fixed without using jQuery but i failed!

If anyone had some thoughts how do deal with this new problem, please let me know!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.