wedevelopnl/ux-table

安装: 400

依赖: 0

建议者: 0

安全: 0

星标: 10

关注者: 5

分支: 2

开放问题: 3

类型:symfony-bundle

v0.4.1 2024-04-25 13:43 UTC

This package is auto-updated.

Last update: 2024-08-25 14:50:52 UTC


README

实验性:此包仍在开发中,一切均可能更改。

描述

UX Table 是一款旨在与 Symfony UX TurboStimulus(Symfony Encore 的一部分)良好协作的数据表。此包旨在利用 超媒体驱动应用(HDA)架构的美丽简洁性。

此包包含用于创建完全灵活数据表的构建块。具体来说,它有助于生成保留 UX 表状态的表单(带有隐藏输入)和链接。

此方法的优势

  • 完全控制模板
  • 无 JavaScript(即使在禁用 JavaScript 的情况下也能工作)
  • 无序列化

先决条件

Symfony UX Turbo

请确保已安装并设置 Symfony UX Turbo。我们严重依赖此功能以提供良好的用户体验。

安装

composer require wedevelopnl/ux-table

使用 Symfony Flex

您应该能够开始。

不使用 Symfony Flex

  1. npm i -D vendor/wedevelopnl/ux-table/assets
  2. 添加到 bundles.php
    WeDevelop\UXTable\WeDevelopUXTableBundle::class => ['all' => true],
  3. 添加到 assets/controllers.json
    {
        "controllers": {
            "@wedevelopnl/ux-table": {
                "ux-table": {
                    "enabled": true,
                    "fetch": "eager"
                }
            }
        },
        "entrypoints": []
    }

入门

创建表单

首先我们创建一个新的表单,它扩展了 WeDevelop\UXTable\Table\AbstractTable

<?php

namespace App\UXTable;

use Symfony\Component\Form\Extension\Core\Type\SearchType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use WeDevelop\UXTable\Table\AbstractTable;

final class ProjectsTable extends AbstractTable
{
    public function getName(): string
    {
        return 'projects';
    }

    protected function buildFilterForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('name', SearchType::class, [
                'attr' => $this->stimulusSearchAttributes(),
                'required' => false,
            ])
        ;
    }

    protected function configureOptions(OptionsResolver $resolver): void
    {
        parent::configureOptions($resolver);

        $resolver->setDefaults([
            'data_class' => \App\Entity\Project::class,
            'sortable_fields' => ['name'],
        ]);
    }
}

这是一个基本的数据表,它为 name 字段添加了过滤器。

创建控制器操作

    #[Route('/projects', name: 'app_project_list')]
    public function listAction(Request $request, ProjectsTable $projectsTable): Response
    {
        $projectsTable->process($request);

        return $this->render(
            'project/list.html.twig',
            ['projectsTable' => $projectsTable]
        );
    }

模板

{# Optional optimization #}
{% extends app.request.headers.has('turbo-frame') ? 'empty.html.twig' : 'page.html.twig' %}

{% block main %}
    <h2>Projects</h2>

    <twig:UXTable:Table :table="projectsTable">
        <table>
            <thead>
            <tr>
                <th>
                    <twig:UXTable:SortLink :table="projectsTable" title="Name" field="name" />
                    <twig:UXTable:Filter :table="projectsTable" filter="name" />
                </th>
                <th></th>
            </tr>
            </thead>
            <tbody>
            {% for project in projectsTable.results %}
                <tr>
                    <td>{{ project.name }}</td>
                    <td><a href="{{ path('app_project_view', {projectId: project.id}) }}" data-turbo-frame="_top">View</a>
                    </td>
                </tr>
            {% endfor %}
            </tbody>
        </table>

        Page size
        {{ form_widget(projectsTable.formView.pageSize) }}

        Pagination
        {{ knp_pagination_render(projectsTable.results) }}
    </twig:UXTable:Table>
{% endblock %}

这里有几个重要的事情。

{% extends app.request.headers.has('turbo-frame') ? 'empty.html.twig' : 'page.html.twig' %}

这确保了在 Turbo Frame 内导航时,我们确保不渲染整个布局,以提高性能。

<twig:UXTable:Table :table="projectsTable">

我们使用 UX Table Twig 组件,这是一个非常精简的组件,确保一切都被包裹在 stimulus 控制器、turbo frame 和表单标签中

<twig:UXTable:SortLink :table="projectsTable" title="Name" field="name" />

这里我们利用 SortLink Twig 组件生成一个保留 UX 表状态的查询参数的链接。

<twig:UXTable:Filter :table="projectsTable" filter="name" />

这里我们利用 Filter Twig 组件显示该过滤器的表单字段。

数据提供者

默认情况下,此包依赖于 DoctrineORMProvider 以自动查询数据库。

如果您想使用自定义填充,可以为 DoctrineORMProvider 配置填充器

protected function configureOptions(OptionsResolver $resolver): void
{
    parent::configureOptions($resolver);

    $resolver->setDefaults([
        'data_class' => \App\Entity\Project::class,
        'hydrator' => function (array $project) {
            return new \App\ReadModel\Project($project['id'], $project['name']);
        },
        'sortable_fields' => ['name'],
    ]);
}

您也可以通过创建一个实现 WeDevelop\UXTable\DataProvider\DataProviderInterface 的类来创建自己的数据提供者。

final class ProjectsProvider implements DataProviderInterface
{
    public function __construct(
        private readonly ApiClient $api,
        private readonly PaginatorInterface $paginator,
    ) {
    }

    public function search(
        array $filters = [],
        array $sort = [],
        int $page = 1,
        int $pageSize = 50,
        array $options = []
    ): PaginationInterface {
        $status = $options['status'];

        $projects = $this->api->getProjects($status, $filters, $sort, $page, $pageSize);

        return $this->paginator->paginate($projects, $page, $pageSize, [PaginatorInterface::PAGE_OUT_OF_RANGE => PaginatorInterface::PAGE_OUT_OF_RANGE_THROW_EXCEPTION]);
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver
            ->define('status')->allowedTypes(ProjectStatus::class)->required()
        ;
    }
}

这里我们还定义了一个可以传递给 process 函数的状态选项

$projectsTable->process($request, options: ['status' => 'active']);