¿Cómo crear una tabla con estilo admin en WordPress?

6 sept 2010, 15:18:30
Vistas: 69.9K
Votos: 53

¿Cuál es la forma recomendada de crear una página con una tabla, siguiendo el estilo de las tablas que muestran entradas o usuarios en el área de administración?

Estoy expandiendo el plugin Cache Images, y contiene una tabla con dominios y un número de imágenes de ese dominio. Por lo tanto, no hay una tabla equivalente existente sobre la cual pueda construir (en la primera versión de esta pregunta, pregunté sobre una tabla con entradas, pero ahí podría (tal vez) expandir la tabla de entradas existente).

¿Debería simplemente basarme en la página de vista general de entradas, y comenzar con un <table class="widefat">, o hay mejores funciones que manejen esto ahora? ¿Conocen algún ejemplo limpio y vacío de una tabla con paginación en el que pueda basar mi trabajo?

2
Comentarios

Hay un nuevo blog para la guía de estilos de la interfaz de usuario de WordPress, puede que te sea útil. http://dotorgstyleguide.wordpress.com/outline/

sorich87 sorich87
27 sept 2010 17:09:01

Nota para mí mismo: scribu añadió un nuevo sistema de tablas con AJAX en WP 3.1, con una clase base WP_List_Table. Esta pregunta probablemente se pueda actualizar con información sobre cómo usarlo.

Jan Fabry Jan Fabry
28 dic 2010 10:50:40
Todas las respuestas a la pregunta 7
5
47

Esto es lo que generalmente uso:

<table class="widefat fixed" cellspacing="0">
    <thead>
    <tr>

            <th id="cb" class="manage-column column-cb check-column" scope="col"></th> // esta columna contiene casillas de verificación
            <th id="columnname" class="manage-column column-columnname" scope="col"></th>
            <th id="columnname" class="manage-column column-columnname num" scope="col"></th> // "num" añadido porque la columna contiene números

    </tr>
    </thead>

    <tfoot>
    <tr>

            <th class="manage-column column-cb check-column" scope="col"></th>
            <th class="manage-column column-columnname" scope="col"></th>
            <th class="manage-column column-columnname num" scope="col"></th>

    </tr>
    </tfoot>

    <tbody>
        <tr class="alternate">
            <th class="check-column" scope="row"></th>
            <td class="column-columnname"></td>
            <td class="column-columnname"></td>
        </tr>
        <tr>
            <th class="check-column" scope="row"></th>
            <td class="column-columnname"></td>
            <td class="column-columnname"></td>
        </tr>
        <tr class="alternate" valign="top"> // esta fila contiene acciones
            <th class="check-column" scope="row"></th>
            <td class="column-columnname">
                <div class="row-actions">
                    <span><a href="#">Acción</a> |</span>
                    <span><a href="#">Acción</a></span>
                </div>
            </td>
            <td class="column-columnname"></td>
        </tr>
        <tr valign="top"> // esta fila contiene acciones
            <th class="check-column" scope="row"></th>
            <td class="column-columnname">
                <div class="row-actions">
                    <span><a href="#">Acción</a> |</span>
                    <span><a href="#">Acción</a></span>
                </div>
            </td>
            <td class="column-columnname"></td>
        </tr>
    </tbody>
</table>

Espero que esto ayude.

6 sept 2010 21:33:51
Comentarios

¿también es posible tener una paginación automática insertada así? (ej. mostrando posts 1-20)

Michiel Standaert Michiel Standaert
7 dic 2011 16:50:05

@MichielStandaert No.

kaiser kaiser
14 jun 2014 14:19:34

@MichielStandaert si quieres un resultado paginado puedes usar paginate_links

tiltdown tiltdown
27 sept 2014 01:09:56

¡Gracias! (Pero sigo preguntándome por qué no usaron :odd para las filas en lugar de hacernos agregar una clase cada dos filas...)

Zachary Dahan Zachary Dahan
15 mar 2016 17:57:33

Obviamente hay soluciones "mejores" (como las otras respuestas aquí), pero para una tabla básica y rápida, esto era exactamente lo que buscaba. ¡Gracias!

rinogo rinogo
1 nov 2019 22:06:37
8
33

Utiliza la API del Core, no solo su CSS

Normalmente solo utilizas una instancia de la clase WP_List_Table.

Guías:

¿Beneficios?

¡SÍ!

Puedes añadir paginación, cajas de búsqueda, acciones y cualquier magia que puedas imaginar (y seas capaz de programar).

19 dic 2012 02:16:18
Comentarios

Pequeña pista como enlace para ver el marcado, clases para la interfaz de administración, sin otro objetivo que crear tablas: https://github.com/bueltge/WordPress-Admin-Style

bueltge bueltge
4 nov 2013 15:33:00

>El acceso a esta clase está marcado como privado. Eso significa que no está destinado para su uso por parte de desarrolladores de plugins y temas, ya que puede cambiar sin previo aviso en cualquier versión futura de WordPress. Si aún deseas hacer uso de la clase, deberías hacer una copia para usar y distribuir con tu propio proyecto, o usarla bajo tu propio riesgo.

Austin Pray Austin Pray
20 may 2017 04:16:50

@AustinPray ¿Una copia? No, por favor no hagas eso. Hay versiones beta, RC y otras pre-release de WP disponibles. Simplemente actualiza tu implementación/extensión. Si realmente tienes que ir por otro camino, escribe algo mejor por tu cuenta. El código del núcleo no es tan bueno.

kaiser kaiser
21 may 2017 02:13:59

@kaiser No mates al mensajero, esas no son mis palabras. Estaba citando del WP Codex. Aunque registrarte para pruebas de regresión perpetuas con cada beta y RC no suena mucho mejor que copiar la clase. Estoy de acuerdo en que escribir tu propia clase simple es un mejor camino a seguir.

Austin Pray Austin Pray
22 may 2017 22:15:09

@AustinPray Sin resentimientos :) El Codex está escrito por personas como tú y yo. De hecho, puedes ir ahora y revertir esa declaración y la gente la citará.

kaiser kaiser
22 may 2017 22:36:31

Desafortunadamente, ambas guías están terriblemente desactualizadas, a partir de Wordpress 5, lo que descubrí por las malas al romper cosas (Además, la de Smashing Magazine tiene errores de sintaxis evidentes - alguien no dominó el copiar y pegar). No he encontrado una alternativa actualizada (el custom-list-table-example es solo ligeramente mejor) y el Codex tiene muchas cosas faltantes. Logré escribir una implementación simple mirando el propio Wordpress, especialmente class-wp-users-list-table.php que está casi completamente funcional pero más simple que otras clases de WP.

Guss Guss
7 jun 2020 18:06:05

@Guss La respuesta es del 2012. Quizás quieras añadir tu propia respuesta para ofrecer una solución más actualizada :)

kaiser kaiser
8 jun 2020 23:51:46

@Kaiser - ya lo hice. Mira abajo :-)

Guss Guss
9 jun 2020 12:02:03
Mostrar los 3 comentarios restantes
2
13

Utiliza este ejemplo (escrito como un plugin) para crear tus tablas de administración:

http://wordpress.org/extend/plugins/custom-list-table-example/

Utiliza la clase incorporada WP_List_Table.

24 dic 2011 19:44:37
Comentarios

Creo que esta debería ser la respuesta aceptada. También puedes ver este artículo en Smashing Magazine que plantea un enfoque similar: http://wp.smashingmagazine.com/2011/11/03/native-admin-tables-wordpress/

julien_c julien_c
10 mar 2012 15:09:52

Este plugin ya no recibe mantenimiento y no funciona con WordPress 5.

Guss Guss
18 abr 2021 17:58:32
0

También puedes usar este pequeño plugin para ver las posibilidades del backend en WP: https://github.com/bueltge/WordPress-Admin-Style

27 may 2011 16:48:57
0

Hay muchas buenas opciones aquí. Pero no hay una rápida y sencilla:

<table class="widefat striped fixed">
    <thead>
        <tr>
            <th>Encabezado1</th>
            <th>Encabezado2</th>
            <th>Encabezado3</th>
        </tr>
    </thead>

    <tbody>
        <tr>
            <td>Contenido1</td>
            <td>Contenido2</td>
            <td>Contenido3</td>
        </tr>
    </tbody>

    <tfoot>
        <tr>
            <th>Pie1</th>
            <th>Pie2</th>
            <th>Pie3</th>
        </tr>
    </tfoot>
</table>

Explicación

  • La clase widefat es usada por el common.css, cargado en el administrador, para que parezca una tabla de WP.
  • La clase striped le da un aspecto de rayas (qué sorpresa).
  • La clase fixed añade el CSS: table-layout: fixed;
28 dic 2021 19:04:37
1

Para aquellos que buscan implementar WP_List_Table, ten en cuenta que todas las guías que encontré están lamentablemente desactualizadas y te harán escribir código redundante o incluso te pedirán que hagas cosas que ya no funcionan.

Aquí tienes un ejemplo mínimo que funciona hasta cierto punto. Debería ser fácil de entender sin una "guía" y te ayudará a comenzar.

Incluye:

  • filtros rápidos (vistas)
  • cuadro de búsqueda
  • acciones de fila

Faltan:

  • configuración del tamaño de página (realmente no he visto que una página de WordPress use esto)
  • acciones masivas
  • filtros desplegables
class Mi_Tabla_Lista extends WP_List_Table {

    function __construct() {
        parent::__construct([
            'singular' => 'empleado',
            'plural' => 'empleados',
        ]);
    }

    function get_columns() {
        return [
            'name'      => __('Nombre'),
            'employer' => __('Empleador'),
            'rank'     => __('Rango'),
            'phone'    => __('Teléfono'),
            'joined'   => __('Fecha de Ingreso'),
        ];
    }

    /* Opcional - sin esto ninguna columna es ordenable */
    public function get_sortable_columns() {
        return [
           // las claves son "nombre_columna" como arriba
           // los valores son nombres de campo "orden" según lo que necesite tu modelo de datos
            'name'     => 'name',
            'employer' => 'employer',
            'rank'     => 'rank',
            'joined'   => 'joined',
        ];
    }

    public function prepare_items() {
       // soporte para el cuadro de búsqueda
        $search = @$_REQUEST['s'] ? wp_unslash(trim($_REQUEST['s']))) : '';
       // obtener la configuración de número de registros por página del almacenamiento de opciones
        $per_page = $this->get_items_per_page('mi_tabla_lista_por_pagina');
       // llenar el array de datos con los elementos de tu modelo. En mi implementación estos
       // son instancias de StdClass con varios campos, pero puede ser cualquier cosa
       // lo veremos en un momento cómo.
        $this->items = obtener_elementos_modelo([
            'offset' => ($this->get_pagenum()-1)*$per_page,
            'count' => $per_page,
            'orderby' => @$_GET["orderby"] ?: 'id', // campo de orden predeterminado, si no se especifica
            'order' => @$_GET["order"] ?: 'ASC', // dirección de orden predeterminada
            'search' => $search, // pasar campo de búsqueda si está configurado
            'status' => @$_REQUEST['status'] // pasar filtro de vista, si está configurado [ver get_views()]
        );
        $this->set_pagination_args([
            "total_items" => obtener_conteo_elementos_modelo(),
            "per_page" => $per_page,
        ]);
       // `obtener_conteo_elementos_modelo` debe ser el número total de registros después
       // del filtrado (vistas y búsqueda) pero antes de la paginación. Esto puede ser difícil/ineficiente
       // de hacer con MySQL. Si deseas poner aquí los resultados de `COUNT(*)`,
       // nadie te culpará.
    }

    public function column_default($item, $column_name) {
        // presentación predeterminada de columna
        // La mayoría de los campos de mi objeto son imprimibles tal cual, así que tenemos un método
        // genérico para manejar eso.
        return $item->$column_name;
    }

    /* Opcional, a menos que tengas datos que requieran formato especial */
    public function column_joined($item) {
        // El campo 'joined' es un objeto DateTime y no puede ser convertido implícitamente
       // a string por la lógica incorporada, así que necesitaremos hacerlo
        return $item->joined->format("Y-m-d");
    }

   /* Opcional - dibujar filtros rápidos en la parte superior de la tabla */
    public function get_views() {
        $crear_enlace = function($valor_filtro, $nombre) { // herramienta DRY para creadores de vistas
            $nombre_filtro = 'status';
            return '<a href="'
                . esc_url(add_query_arg($nombre_filtro, $valor_filtro)) . '" ' .
                (@$_REQUEST[$nombre_filtro]==$valor_filtro ? 
                    'class="current" aria-current="page"' : ''). ">" .
                $nombre . "</a>";
        };
        return [
            'all' => $crear_enlace(false, __('Todos')),
            'green' => $crear_enlace('green', __('Novatos')),
            'pros' => $crear_enlace('pro', __('Expertos')),
            'bofh' => $crear_enlace('veterano', __('Tipos veteranos')),
        ];
    }

    /* Opcional: acciones de fila */
    public function handle_row_actions($item, $column_name, $primary) {
        $salida = parent::handle_row_actions($item, $column_name, $primary);
        if ($column_name === $primary)
            $salida .= $this->row_actions([
                'editar' => sprintf('<a href="%s">%s</a>',
                    add_query_arg('employee_id', $item->id, admin_url('admin.php?page=editar-empleado')),
                    __("Editar")),
                'eliminar' => sprintf('<a href="%s">%s</a>',
                    add_query_arg('employee_id', $item->id, admin_url('admin.php?page=eliminar-empleado')),
                    __("Eliminar")),
            ]);
        return $salida;
    }

}

Entonces la función de la página de administración (para add_menu_page/add_submenu_page) podría verse así:

function dibujarPaginaAdmin() {
    $mi_tabla_lista = new Mi_Tabla_Lista();
    $mi_tabla_lista->prepare_items();
    ?>
    <div class="wrap">
    <h1 class="wp-heading-inline"><?php _e('Título de la Página de Admin')?></h1>
    <hr class="wp-header-end">
    <?php $mi_tabla_lista->views() ?>
    <form id="employee-filter" method="get">
    <input type="hidden" name="page" value="<?php echo $_REQUEST['page']?>">
    <?php $mi_tabla_lista->search_box(__('Buscar'), 'empleado') ?>
    <?php $mi_tabla_lista->display(); ?>
    </form>
    </div>
    <?php
}
7 jun 2020 18:26:05
Comentarios

Ahí va tu voto positivo.

kaiser kaiser
9 jun 2020 12:21:28
2

¿Quizás quieras considerar agregar un filtro a la lista de tu tipo de entrada personalizada en el administrador? La respuesta enlazada abajo muestra cómo hacerlo con una taxonomía, pero podrías fácilmente usar otros criterios en tu hook restrict_manage_posts:

Déjame saber si tienes más preguntas.

7 sept 2010 05:03:08
Comentarios

Me disculpo por la pregunta poco clara. En mi primer ejemplo era una tabla de publicaciones, y de hecho, podría intentar usar la tabla de publicaciones existente para eso (¿incluso si solo quiero mostrar los títulos de las publicaciones y luego todas las columnas personalizadas?). Pero ahora he editado mi pregunta con un ejemplo concreto: tengo una tabla de dominios, así que no hay una tabla existente equivalente que pueda expandir.

Jan Fabry Jan Fabry
7 sept 2010 10:50:50

@Jan: Ah. Sí, creo que has dado con la verdad, que no hay una buena forma encapsulada de hacer esto aparte de escribir HTML (duplicado). A menudo he tenido el mismo problema. Tal vez crea un ticket en trac solicitando esta mejora y enlace la URL/número de ticket aquí para que podamos apoyarlo.

MikeSchinkel MikeSchinkel
8 sept 2010 02:07:58