Создание таблицы в стиле админ-панели?

6 сент. 2010 г., 15:18:30
Просмотры: 69.9K
Голосов: 53

Какой рекомендуемый способ создания страницы с таблицей в стиле таблиц, отображающих записи или пользователей в области администрирования?

Я расширяю плагин Cache Images, и он содержит таблицу с доменами и количеством изображений с этого домена. Поэтому нет эквивалентной существующей таблицы, на которой я мог бы основываться (в первой версии этого вопроса я спрашивал о таблице с записями, но там я мог (возможно) расширить существующую таблицу записей).

Стоит ли мне просто основываться на странице обзора записей и начать с <table class="widefat">, или есть лучшие функции, которые сейчас обрабатывают это? Знаете ли вы чистый, пустой пример таблицы с пагинацией, на котором я мог бы основывать свою работу?

2
Комментарии

Появился новый блог, посвященный гайдлайнам пользовательского интерфейса WordPress, возможно, он вам пригодится. http://dotorgstyleguide.wordpress.com/outline/

sorich87 sorich87
27 сент. 2010 г. 17:09:01

Заметка себе: scribu добавил новую систему ajax-таблиц в WP 3.1, с базовым классом WP_List_Table. Возможно, стоит обновить этот вопрос информацией о том, как его использовать.

Jan Fabry Jan Fabry
28 дек. 2010 г. 10:50:40
Все ответы на вопрос 7
5
47

Вот что я обычно использую:

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

            <th id="cb" class="manage-column column-cb check-column" scope="col"></th> // эта колонка содержит чекбоксы
            <th id="columnname" class="manage-column column-columnname" scope="col"></th>
            <th id="columnname" class="manage-column column-columnname num" scope="col"></th> // "num" добавлен, потому что колонка содержит числа

    </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"> // эта строка содержит действия
            <th class="check-column" scope="row"></th>
            <td class="column-columnname">
                <div class="row-actions">
                    <span><a href="#">Действие</a> |</span>
                    <span><a href="#">Действие</a></span>
                </div>
            </td>
            <td class="column-columnname"></td>
        </tr>
        <tr valign="top"> // эта строка содержит действия
            <th class="check-column" scope="row"></th>
            <td class="column-columnname">
                <div class="row-actions">
                    <span><a href="#">Действие</a> |</span>
                    <span><a href="#">Действие</a></span>
                </div>
            </td>
            <td class="column-columnname"></td>
        </tr>
    </tbody>
</table>

Надеюсь, это поможет.

6 сент. 2010 г. 21:33:51
Комментарии

можно ли также автоматически вставлять пагинацию вот так? (например, показывать записи 1-20)

Michiel Standaert Michiel Standaert
7 дек. 2011 г. 16:50:05

@MichielStandaert Нет.

kaiser kaiser
14 июн. 2014 г. 14:19:34

@MichielStandaert если вам нужен пагинированный результат, вы можете использовать paginate_links

tiltdown tiltdown
27 сент. 2014 г. 01:09:56

Спасибо! (Но я всё ещё спрашиваю себя, почему они не использовали :odd для строк вместо того, чтобы заставлять нас добавлять класс каждые две строки...)

Zachary Dahan Zachary Dahan
15 мар. 2016 г. 17:57:33

Очевидно, существуют "лучшие" решения (как другие ответы здесь), но для быстрой, базовой таблицы это именно то, что мне было нужно. Спасибо!

rinogo rinogo
1 нояб. 2019 г. 22:06:37
8
33

Используйте Core API, а не только его CSS

Обычно вы просто используете экземпляр класса WP_List_Table.

Руководства:

  • Подробнее об этом в Codex здесь.
  • Также руководство от WP Engineer - слишком объемное, чтобы копировать его сюда.
  • И еще одно руководство на Smashing Magazine в сети.

Преимущества?

ДА!

Вы можете добавить пагинацию, поисковые поля, действия и любую магию, которую только сможете вообразить (и сумеете запрограммировать).

19 дек. 2012 г. 02:16:18
Комментарии

Небольшая подсказка в виде ссылки для просмотра разметки и классов административного интерфейса, только с целью создания таблиц: https://github.com/bueltge/WordPress-Admin-Style

bueltge bueltge
4 нояб. 2013 г. 15:33:00

>Доступ к этому классу помечен как приватный. Это означает, что он не предназначен для использования разработчиками плагинов и тем, так как может быть изменен без предупреждения в любом будущем релизе WordPress. Если вы все же хотите использовать этот класс, вам следует создать его копию для использования и распространения в рамках вашего проекта, либо использовать его на свой страх и риск.

Austin Pray Austin Pray
20 мая 2017 г. 04:16:50

@AustinPray Копию? Нет, пожалуйста, не делайте этого. Существуют бета-версии, релиз-кандидаты и другие предварительные версии WordPress. Просто обновите свою реализацию/расширение. Если вам действительно нужно пойти другим путем, просто напишите что-то лучше самостоятельно. Код ядра не настолько хорош.

kaiser kaiser
21 мая 2017 г. 02:13:59

@kaiser Не стреляйте в гонца, это не мои слова. Я цитировал WP Codex. Хотя подписаться на бесконечное регрессионное тестирование с каждым бета- и RC-релизом не звучит намного лучше, чем копирование класса. Согласен, что написание собственного простого класса — это более правильный путь.

Austin Pray Austin Pray
22 мая 2017 г. 22:15:09

@AustinPray Без обид :) Codex написан такими же людьми, как вы и я. Фактически, вы можете прямо сейчас исправить это утверждение, и люди будут цитировать его.

kaiser kaiser
22 мая 2017 г. 22:36:31

К сожалению, оба руководства безнадежно устарели, начиная с WordPress 5, что я понял на собственном горьком опыте, ломая вещи (также в руководстве от Smashing Magazine есть вопиющие синтаксические ошибки — кто-то не справился с копированием и вставкой). Я не нашел актуальной альтернативы (custom-list-table-example лишь немного лучше), а в Codex многое отсутствует. Мне удалось написать простую реализацию, изучая сам WordPress, особенно class-wp-users-list-table.php, который почти полностью функционален, но проще других WP-классов.

Guss Guss
7 июн. 2020 г. 18:06:05

@Guss Этот ответ из 2012 года. Возможно, вы захотите добавить свой собственный ответ, чтобы предложить более современное решение :)

kaiser kaiser
8 июн. 2020 г. 23:51:46

@Kaiser - уже сделал. Смотри ниже :-)

Guss Guss
9 июн. 2020 г. 12:02:03
Показать остальные 3 комментариев
2
13

Используйте этот пример (написанный в виде плагина) для создания своих административных таблиц:

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

Он использует встроенный класс WP_List_Table.

24 дек. 2011 г. 19:44:37
Комментарии

Я считаю, что этот ответ должен быть принятым. Также ознакомьтесь с этой статьей в Smashing Magazine, где описывается похожий подход: http://wp.smashingmagazine.com/2011/11/03/native-admin-tables-wordpress/

julien_c julien_c
10 мар. 2012 г. 15:09:52

Этот плагин больше не поддерживается и не работает с WordPress 5.

Guss Guss
18 апр. 2021 г. 17:58:32
0

Также вы можете использовать этот небольшой плагин для просмотра возможностей бэкенда в WP: https://github.com/bueltge/WordPress-Admin-Style

27 мая 2011 г. 16:48:57
0

Здесь представлено много хороших вариантов. Но нет быстрого и грязного решения:

<table class="widefat striped fixed">
    <thead>
        <tr>
            <th>Заголовок1</th>
            <th>Заголовок2</th>
            <th>Заголовок3</th>
        </tr>
    </thead>

    <tbody>
        <tr>
            <td>Содержимое1</td>
            <td>Содержимое2</td>
            <td>Содержимое3</td>
        </tr>
    </tbody>

    <tfoot>
        <tr>
            <th>Подвал1</th>
            <th>Подвал2</th>
            <th>Подвал3</th>
        </tr>
    </tfoot>
</table>

Пояснение

  • Класс widefat используется в common.css, который загружается в админке, чтобы таблица выглядела как стандартная WP-таблица.
  • Класс striped добавляет полосатый фон (как ни удивительно).
  • Класс fixed добавляет CSS-свойство: table-layout: fixed;
28 дек. 2021 г. 19:04:37
1

Для тех, кто хочет реализовать WP_List_Table, обратите внимание, что все найденные мной руководства устарели и либо содержат избыточный код, либо предлагают решения, которые больше не работают.

Вот минимальный рабочий пример, который должен быть понятен без дополнительных "руководств" и поможет вам начать.

Включено:

  • быстрые фильтры (представления)
  • поисковая строка
  • действия со строками

Отсутствует:

  • настройка размера страницы (я не видел, чтобы WordPress использовал это)
  • массовые действия
  • выпадающие фильтры
class My_List_Table extends WP_List_Table {

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

    function get_columns() {
        return [
            'name'      => __('Имя'),
            'employer' => __('Работодатель'),
            'rank'     => __('Должность'),
            'phone'    => __('Телефон'),
            'joined'   => __('Дата приема'),
        ];
    }

    /* Опционально - без этого столбцы нельзя сортировать */
    public function get_sortable_columns() {
        return [
           // ключи - названия столбцов, как выше
           // значения - названия полей для сортировки, которые требуются вашей модели данных
            'name'     => 'name',
            'employer' => 'employer',
            'rank'     => 'rank',
            'joined'   => 'joined',
        ];
    }

    public function prepare_items() {
       // поддержка поисковой строки
        $search = @$_REQUEST['s'] ? wp_unslash(trim($_REQUEST['s']))) : '';
       // получаем количество записей на страницу из настроек
        $per_page = $this->get_items_per_page('my_list_table_per_page');
       // заполняем массив данных элементами вашей модели. В моей реализации это
       // объекты StdClass с различными полями, но это может быть что угодно,
       // как мы увидим далее.
        $this->items = get_model_items([
            'offset' => ($this->get_pagenum()-1)*$per_page,
            'count' => $per_page,
            'orderby' => @$_GET["orderby"] ?: 'id', // поле для сортировки по умолчанию, если не указано
            'order' => @$_GET["order"] ?: 'ASC', // направление сортировки по умолчанию
            'search' => $search, // передаем строку поиска, если задана
            'status' => @$_REQUEST['status'] // передаем фильтр представления, если задан [см. get_views()]
        );
        $this->set_pagination_args([
            "total_items" => get_model_item_count(),
            "per_page" => $per_page,
        ]);
       // `get_model_item_count` должно быть общим количеством записей после
       // фильтрации (представления и поиск), но до пагинации. Это может быть сложно/неэффективно
       // реализовать в MySQL. Если вы хотите использовать здесь результат `COUNT(*)`,
       // вас никто не осудит.
    }

    public function column_default($item, $column_name) {
        // стандартное представление столбца
        // Большинство полей моего объекта можно выводить как есть, поэтому у нас есть
        // общий метод для обработки этого.
        return $item->$column_name;
    }

    /* Опционально, если у вас есть данные, требующие специального форматирования */
    public function column_joined($item) {
        // Поле 'joined' является объектом DateTime и не может быть неявно
       // преобразовано в строку встроенной логикой, поэтому нам нужно сделать это вручную
        return $item->joined->format("Y-m-d");
    }

   /* Опционально - рисуем быстрые фильтры над таблицей */
    public function get_views() {
        $makelink = function($filter_val, $name) { // инструмент для DRY при создании представлений
            $filter_name = 'status';
            return '<a href="'
                . esc_url(add_query_arg($filter_name, $filter_val)) . '" ' .
                (@$_REQUEST[$filter_name]==$filter_val ? 
                    'class="current" aria-current="page"' : ''). ">" .
                $name . "</a>";
        };
        return [
            'all' => $makelink(false, __('Все')),
            'green' => $makelink('green', __('Новички')),
            'pros' => $makelink('pro', __('Профессионалы')),
            'bofh' => $makelink('veteran', __('Опытные сотрудники')),
        ];
    }

    /* Опционально: действия со строками */
    public function handle_row_actions($item, $column_name, $primary) {
        $out = parent::handle_row_actions($item, $column_name, $primary);
        if ($column_name === $primary)
            $out .= $this->row_actions([
                'edit' => sprintf('<a href="%s">%s</a>',
                    add_query_arg('employee_id', $item->id, admin_url('admin.php?page=edit-employee')),
                    __("Редактировать")),
                'delete' => sprintf('<a href="%s">%s</a>',
                    add_query_arg('employee_id', $item->id, admin_url('admin.php?page=delete-employee')),
                    __("Удалить")),
            ]);
        return $out;
    }

}

Функция для страницы администратора (для add_menu_page/add_submenu_page) может выглядеть так:

function drawAdminPage() {
    $my_list_table = new My_List_Table();
    $my_list_table->prepare_items();
    ?>
    <div class="wrap">
    <h1 class="wp-heading-inline"><?php _e('Заголовок страницы администратора')?></h1>
    <hr class="wp-header-end">
    <?php $my_list_table->views() ?>
    <form id="employee-filter" method="get">
    <input type="hidden" name="page" value="<?php echo $_REQUEST['page']?>">
    <?php $my_list_table->search_box(__('Поиск'), 'employee') ?>
    <?php $my_list_table->display(); ?>
    </form>
    </div>
    <?php
}
7 июн. 2020 г. 18:26:05
Комментарии

Вот твой голос за.

kaiser kaiser
9 июн. 2020 г. 12:21:28
2

Возможно, вы хотели бы добавить фильтр к списку вашего пользовательского типа записей в админке? В приведённом ниже ответе показано, как это сделать с таксономией, но вы легко можете использовать другие критерии в вашем хуке restrict_manage_posts:

Дайте мне знать, если у вас есть дополнительные вопросы.

7 сент. 2010 г. 05:03:08
Комментарии

Извините за нечеткий вопрос. В моем первом примере это была таблица записей, и действительно, я мог бы попробовать использовать существующую таблицу записей для этого (даже если я хочу отображать только заголовки записей и затем все пользовательские колонки?). Но теперь я отредактировал свой вопрос с конкретным примером: у меня есть таблица доменов, так что нет эквивалентной существующей таблицы, которую я мог бы расширить.

Jan Fabry Jan Fabry
7 сент. 2010 г. 10:50:50

@Jan: Ах. Да, думаю, вы нашли истину, что нет хорошего инкапсулированного способа сделать это, кроме как писать (дублирующийся) HTML. Я часто сталкивался с такой же проблемой. Может быть, создайте тикет на trac с запросом этого улучшения и пришлите ссылку/номер тикета сюда, чтобы мы могли его поддержать.

MikeSchinkel MikeSchinkel
8 сент. 2010 г. 02:07:58