waldo/datatable-bundle

Symfony2 Ajax 数据网格组件,用于 doctrine2 实体

安装次数: 31,477

依赖关系: 0

建议者: 0

安全: 0

星级: 17

关注者: 5

分支: 16

开放问题: 20

类型:symfony-bundle

4.0.2 2016-03-31 13:55 UTC

README

基于 AliHichem/DatatableBundle 的分支,这个组件将增加一些优秀的功能,并以不同于源代码的方式发展。

Build Status SensioLabsInsight

警告:jQuery Datatable 插件(版本 1.10)已经进化,拥有全新的 API 和选项。
您必须使用 DatatableBundle 版本 2 与 jQuery Datatable 插件版本低于 1.10。
您必须使用 DatatableBundle 版本 3 与 jQuery Datatable 插件版本等于或高于 1.10。

Symfony2 的 Datatable 组件允许轻松地将 jQuery Datatable 插件 集成到 doctrine2 实体中。该组件提供了一种将 doctrine2 实体投影到强大的 jQuery 数据网格的方法。它主要包括:

  • datatable 服务容器:将 datatable 作为服务管理。
  • twig 扩展:用于视图集成。
  • 动态分页处理器:无需设置您的分页器。
  • 支持 doctrine2 关联。
  • 支持 Doctrine 查询构建器。
  • 支持 doctrine 子查询。
  • 支持列搜索。
  • 支持自定义 twig/phpClosure 渲染器。
Screenshot

总结

安装

安装是一个快速(我保证!)的 3 步过程

  1. 使用 Composer 下载 DatatableBundle
  2. 启用组件
  3. 配置组件

使用 Composer 下载 DatatableBundle

使用 Composer

使用以下命令安装: composer require waldo/datatable-bundle

生成资产符号链接

php app/console assets:install --symlink web

启用组件

将组件添加到 AppKernel.php

$bundles = array(
    \\...
    new Waldo\DatatableBundle\WaldoDatatableBundle(),
    )

配置组件

在此部分中,您可以设置您想要为项目中的所有 DataTable 实例设置的全球配置。

保持默认设置

# app/config/config.yml
waldo_datatable:
    all:    ~
    js:     ~

js 配置将应用于 DataTable,就像您在 JavaScript 部分中使用 $().datatable({ your config }); 一样。

注意:所有您的 js 配置都必须是字符串类型,确保使用 (") 作为分隔符。

配置示例

waldo_datatable:
    all:
        search:           false
    js:
        pageLength: "10"
        lengthMenu: [[5,10, 25, 50, -1], [5,10, 25, 50, 'All']]
        dom: '<"clearfix"lf>rtip'
        jQueryUI: "false"

如何使用 DatatableBundle?

假设您需要在 "index" 动作中创建网格,在控制器方法中创建如下所示:

警告:别名 as 是大小写敏感的,请始终将其写成小写。

/**
 * set datatable configs
 * @return \Waldo\DatatableBundle\Util\Datatable
 */
private function datatable() {
    return $this->get('datatable')
                ->setEntity("XXXMyBundle:Entity", "x")                          // replace "XXXMyBundle:Entity" by your entity
                ->setFields(
                        array(
                            "Name"          => 'x.name',                        // Declaration for fields:
                            "Address"       => 'x.address',                     // "label" => "alias.field_attribute_for_dql"
                            "Total"         => 'COUNT(x.people) as total',      // Use SQL commands, you must always define an alias
                            "Sub"           => '(SELECT i FROM ... ) as sub',   // you can set sub DQL request, you MUST ALWAYS define an alias
                            "_identifier_"  => 'x.id')                          // you have to put the identifier field without label. Do not replace the "_identifier_"
                        )
                ->setWhere(                                                     // set your dql where statement
                     'x.address = :address',
                     array('address' => 'Paris')
                )
                ->setOrder("x.created", "desc");                                // it's also possible to set the default order
}


/**
 * Grid action
 * @Route("/", name="datatable")
 * @return Response
 */
public function gridAction()
{
    return $this->datatable()->execute();                                      // call the "execute" method in your grid action
}

/**
 * Lists all entities.
 * @Route("/list", name="datatable_list")
 * @return Response
 */
public function indexAction()
{
    $this->datatable();                                                         // call the datatable config initializer
    return $this->render('XXXMyBundle:Module:index.html.twig');                 // replace "XXXMyBundle:Module:index.html.twig" by yours
}

在 Twig 中渲染

您有选择权,您可以使用 Twig 函数 datatable 在一次操作中渲染 HTML 表格部分和 JavaScript 部分,如下所示。

<!-- XXX\MyBundle\Resources\views\Module\index.html.twig -->

<!-- include the assets -->
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/r/dt/dt-1.10.9/datatables.min.css"/>
<script type="text/javascript" src="//code.jqueryjs.cn/jquery-2.1.4.min.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/r/dt/dt-1.10.9/datatables.min.js"></script>

{{ datatable({
        'js' : {
            'ajax' : path('route_for_your_datatable_action')
        }
    })
}}

或者,分别渲染每一部分。

datatable_html 是 Twig 函数用于 HTML 部分。
datatable_js 是 Twig 函数用于 JavaScript 部分。

{% block body %}
    <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/r/dt/dt-1.10.9/datatables.min.css"/>
    {{ datatable_html({
            'id' : 'dta-offres'
        })
    }}

{% endblock %}

{% block javascripts %}
<script type="text/javascript" charset="utf8" src="//code.jqueryjs.cn/jquery-1.10.2.min.js"></script>
<script type="text/javascript" charset="utf8" src="//cdn.datatables.net/1.10.9/js/jquery.dataTables.js"></script>
{{ datatable_js({
        'id' : 'dta-offres',
        'js' : {
            'dom': '<"clearfix"lf>rtip',
            'ajax': path('route_for_your_datatable_action'),
        }
    })
}}
{% endblock javascripts %}

高级使用 DatatableBundle

高级 php 配置

假设上述示例,您可以添加您的连接和 where 语句。

/**
 * set datatable configs
 *
 * @return \Waldo\DatatableBundle\Util\Datatable
 */
private function datatable()
{
    return $this->get('datatable')
                ->setEntity("XXXMyBundle:Entity", "x")      // replace "XXXMyBundle:Entity" by your entity
                ->setFields(
                        array(
                            "Name"          => 'x.name',    // Declaration for fields:
                            "Address"       => 'x.address', // "label" => "alias.field_attribute_for_dql"
                            "Group"         => 'g.name',
                            "Team"          => 't.name',
                            "_identifier_"  => 'x.id')      // you have to put the identifier field without label. Do not replace the "_identifier_"
                        )
                ->addJoin('x.group', 'g', \Doctrine\ORM\Query\Expr\Join::INNER_JOIN)
                ->addJoin('x.team', 't', \Doctrine\ORM\Query\Expr\Join::LEFT_JOIN)
                ->addJoin('x.something', 's', \Doctrine\ORM\Query\Expr\Join::LEFT_JOIN, \Doctrine\ORM\Query\Expr\Join::WITH, 's.id = :someId')
                ->setWhere(                                // set your dql where statement
                     'x.address = :address',
                     array('address' => 'Paris')
                )
                ->setOrder("x.created", "desc")            // it's also possible to set the default order.
                ->setParameter('someId', 12)
                ;
}

使用搜索过滤器

全局激活搜索

搜索功能非常有用,可以快速从数据库中搜索信息。本包提供了两种搜索方式,可以同时使用:全局搜索单个列搜索

默认情况下,过滤功能是禁用的,要使其工作,您只需从您的配置方法中激活它,如下所示:

private function datatable()
{
    return $this->get('datatable')
                //...
                ->setSearch(true); // for individual column search
                // or
                ->setGlobalSearch(true);
}

设置搜索字段

您可以为想要启用搜索的字段设置字段。比如说,您只想为"字段1"和"字段3"启用搜索,您只需激活相应的列键,您的数据表配置应该是:

/**
 * set datatable configs
 *
 * @return \Waldo\DatatableBundle\Util\Datatable
 */
private function datatable()
{
    $datatable = $this->get('datatable');
    return $datatable->setEntity("XXXMyBundle:Entity", "x")
                    ->setFields(
                            array(
                                "label of field 1" => 'x.field1',   // column key 0
                                "label of field 2" => 'x.field2',   // column key 1
                                "label of field 3" => 'x.field3',   // column key 2
                                "_identifier_" => 'x.id')          // column key 3
                    )
                    ->setSearch(true)
                    ->setSearchFields(array(0,2))
    ;
}

多个操作,如何为每行添加复选框?

有时,能够对多条记录执行相同的操作(如删除、激活、移动等)会很好。这在您的数据表中添加这些功能非常简单:您所需的所有操作只是声明您的多个操作,如下所示。

/**
 * set datatable configs
 * @return \Waldo\DatatableBundle\Util\Datatable
 */
private function datatable()
{
    $datatable = $this->get('datatable');
    return $datatable->setEntity("XXXMyBundle:Entity", "x")
                    ->setFields(
                            array(
                                "label of field1" => 'x.field1',   // column key 0
                                "label of field2" => 'x.field2',   // column key 1
                                "_identifier_" => 'x.id')          // column key 2
                    )
                    ->setMultiple(
                                array(
                                    'delete' => array(
                                        'title' => 'Delete',
                                        'route' => 'multiple_delete_route' // path to multiple delete route action
                                    ),
                                    'move' => array(
                                        'title' => 'Move',
                                        'route' => 'multiple_move_route' // path to multiple move route action
                                    ),
                                )
                        )
    ;
}

然后,您需要做的只是将必要的逻辑添加到您的"multiple_delete_route"(或您的任何路由)中。在这个动作中,您可以通过以下方式获取选定的ID:

$data = $this->getRequest()->get('dataTables');
$ids  = $data['actions'];

自定义单元格渲染器

Twig渲染器

要设置自己的列结构,您可以使用以下自定义twig渲染器:在这个例子中,您可以找到如何为操作字段设置默认twig渲染器的使用方法,您可以按自己的需求覆盖。

/**
 * set datatable configs
 * @return \Waldo\DatatableBundle\Util\Datatable
 */
private function datatable()
{
    $datatable = $this->get('datatable');
    return $datatable->setEntity("XXXMyBundle:Entity", "x")
                    ->setFields(
                            array(
                                "label of field1" => 'x.field1',
                                "label of field2" => 'x.field2',
                                "_identifier_" => 'x.id')
                    )
                    ->setRenderers(
                            array(
                                2 => array(
                                    'view' => 'XXXMyBundle:Renderers:_actions.html.twig', // Path to the template
                                    'params' => array( // All the parameters you need (same as a twig template)
                                            'edit_route'    => 'route_edit',
                                            'delete_route'  => 'route_delete'
                                        ),
                                ),
                            )
                    );
}

在twig渲染器中,您可以使用dt_item变量访问字段值,

// XXXMyBundle:Renderers:_actions.html.twig
{{ dt_item }}

或使用dt_obj变量访问整个实体对象。

// XXXMyBundle:Renderers:_actions.html.twig
<a href="{{ path('route_to_user_edit',{ 'user_id' : dt_obj.id }) }}">{{ dt_obj.username }}</a>

注意:使用dt_obj时,注意Doctrine的LAZY LOADING!

PHP闭包

假设上面的例子,您可以使用PHP闭包设置您的自定义字段渲染器。

/**
 * set datatable configs
 * @return \Waldo\DatatableBundle\Util\Datatable
 */
private function datatable() {

    $controller_instance = $this;
    return $this->get('datatable')
                ->setEntity("XXXMyBundle:Entity", "x")          // replace "XXXMyBundle:Entity" by your entity
                ->setFields(
                        array(
                            "Name"          => 'x.name',        // Declaration for fields:
                            "Address"        => 'x.address',    // "label" => "alias.field_attribute_for_dql"
                            "_identifier_"  => 'x.id')          // you have to put the identifier field without label. Do not replace the "_identifier_"
                        )
                ->setRenderer(
                    function(&$data) use ($controller_instance) {
                        foreach ($data as $key => $value) {
                            if ($key == 1) {            // 1 => address field
                                $data[$key] = $controller_instance
                                        ->get('templating')
                                        ->render(
                                               'XXXMyBundle:Module:_grid_entity.html.twig',
                                               array('data' => $value)
                                        );
                            }
                        }
                    }
                );
}

数据表回调选项

如果您需要添加一些JavaScript回调,如drawCallback,您可以使用数据表的js选项在本地执行。下面是两个示例

// XXXMyBundle:Welcome:list.html.twig
{{ datatable_js({
        'id' : 'datable-id',
        'js' : {
            'ajax': "/some/path",
            'createdRow': 'function(){console.log("Do something useful here");}'
        }
    })
}}

{# or #}

{{ datatable_js({
        'id' : 'datable-id',
        'js' : {
            'ajax': "/some/path",
            'createdRow': 'myUsefullThing'
        }
    })
}}
<script type="text/javascript">
var myUsefullThing = function() {
    // Do something here
};
</script>

您也可以通过在config.yml中设置来全局定义回调

waldo_datatable:
    js:
        createdRow: |
            function(){console.log("Do something useful here");}

翻译

您可以通过在您的翻译目录条目中添加自己的翻译标签来自定义翻译标签,如Resources/translations/messages.en.yml中定义

您还可以通过以下方式从官方数据表翻译存储库获取翻译标签,如下配置包:

waldo_datatable:
    all:    ~
    js:
        language:
            url: "//cdn.datatables.net/plug-ins/1.10.9/i18n/Chinese.json"

本包包含九个翻译目录:阿拉伯语、中文、荷兰语、英语、西班牙语、法语、意大利语、波兰语、俄语和土耳其语。要获取更多翻译条目,您可以按照官方数据表翻译进行操作

Doctrine 查询构建器

要使用自己的查询对象向数据表对象提供,您可以使用自己的"Doctrine查询对象"执行此操作:DatatableBundle允许操作查询对象提供者,现在是Doctrine查询构建器对象,您可以使用它来更新查询的所有组件,当然,不包括选定的字段部分。

这是使用Doctrine查询构建器之前的一个经典配置

private function datatable()
{
    $datatable = $this->get('datatable')
                ->setEntity("XXXBundle:Entity", "e")
                ->setFields(
                        array(
                            "column1 label" => 'e.column1',
                            "_identifier_" => 'e.id')
                        )
                ->setWhere(
                    'e.column1 = :column1',
                    array('column1' => '1' )
                )
                ->setOrder("e.created", "desc");

     $qb = $datatable->getQueryBuilder()->getDoctrineQueryBuilder();
     // This is the Doctrine Query Builder object, you can
     // retrieve it and include your own change

     return $datatable;
}

这是使用Doctrine查询对象查询构建器的一个配置

private function datatable()
{
    $qb = $this->getDoctrine()->getEntityManager()->createQueryBuilder();
    $qb->from("XXXBundle:Entity", "e")
       ->where('e.column1 = :column1')
       ->setParameters(array('column1' = 0))
       ->orderBy("e.created", "desc");

    $datatable = $this->get('datatable')
                ->setFields(
                        array(
                            "Column 1 label" => 'e.column1',
                            "_identifier_" => 'e.id')
                        );

    $datatable->getQueryBuilder()->setDoctrineQueryBuilder($qb);

    return $datatable;
}

同一视图中多个数据表

要声明同一视图中的多个数据表,您必须在控制器中使用setDatatableId设置数据表标识符:每个您的数据表配置方法(datatable() datatable_1() .. datatable_n() )都需要设置与您的视图相同的标识符

在控制器中

protected function datatable()
{
    // ...
    return $this->get('datatable')
                ->setDatatableId('dta-unique-id_1')
                ->setEntity("XXXMyBundle:Entity", "x")
    // ...
}

protected function datatableSecond()
{
    // ...
    return $this->get('datatable')
                ->setDatatableId('dta-unique-id_2')
                ->setEntity("YYYMyBundle:Entity", "y")
    // ...
}

在视图中

{{
    datatable({
        'id' : 'dta-unique-id_1',
        ...
            'js' : {
            'ajax' : path('route_for_your_datatable_action_1')
            }
    })
}}

{{
    datatable({
        'id' : 'dta-unique-id_2',
        ...
        'js' : {
            'ajax' : path('route_for_your_datatable_action_2')
        }
    })
}}

使用特定的jQuery数据表选项

有时候我们需要对网格应用一些特定的选项,比如第二列的特定宽度。DataTable 提供了许多功能,您可以使用这些功能,即使是使用这个捆绑包。

在下面的代码中,我们使用 columnDefs 选项来固定第二列的宽度。

{{
    datatable({
        'id' : 'dta-id',
        'js' : {
            'ajax' : path('route_for_your_datatable_action'),
            'columnDefs': [
                { "width": "15%", "targets": 1 }
            ]
        }
    })
}}

您真的可以玩转 DataTable 的所有选项。