zoukankan      html  css  js  c++  java
  • Yii2 GridView自定义链接之重写 ActionColumn

    最近刚开始用yii2,真是超棒的,但是也有许多不足的地方,今天要说的就是GridView链接问题。

     
    <?= GridView::widget([
        'dataProvider' => $dataProvider,
        'filterModel' => $searchModel,
        'columns' => [
            ['class' => 'yiigridSerialColumn'],
            'id',
            'username',
            'email',
            ['class' => 'yiigridActionColumn'],
        ],
    ]); ?>
    

    这是一个最简单的默认 GridView,gii生成的就这样,那么问题来了。
    如果用户管理不是独立的控制器,而是在user控制器或者是site控制器下,ActionColumn默认链接却是view, update, delete
    但是我想要的却是 user-view, user-update, user-delete 这样的链接,然后我修改了下,代码如下。

     
    <?= GridView::widget([
        'dataProvider' => $dataProvider,
        'filterModel' => $searchModel,
        'columns' => [
            ['class' => 'yiigridSerialColumn'],
            'id',
            'username',
            'email',
            [
                'class' => 'yiigridActionColumn',
                'template' => '{user-view} {user-update} {user-delete}',
            ],
        ],
    ]); ?>
    

    结果,什么都没了,为什么呢?然后我打开 yiigridActionColumn,看了源码,发现他默认只渲染了view, update, delete
    如果 {user-view} 这样的标签在按钮组(buttons[])里不存在,就输出空。

    所以我们还要添加按钮才行,然后代码就成了这样。

     
    <?= GridView::widget([
        'dataProvider' => $dataProvider,
        'filterModel' => $searchModel,
        'columns' => [
            ['class' => 'yiigridSerialColumn'],
            'id',
            'username',
            'email',
            [
                'class' => 'yiigridActionColumn',
                'template' => '{user-view} {user-update} {user-delete}',
                'buttons' = [
                    // 下面代码来自于 yiigridActionColumn 简单修改了下
                    'user-view' => function ($url, $model, $key) {
                        $options = [
                            'title' => Yii::t('yii', 'View'),
                            'aria-label' => Yii::t('yii', 'View'),
                            'data-pjax' => '0',
                        ];
                        return Html::a('<span class="glyphicon glyphicon-eye-open"></span>', $url, $options);
                    },
                    'user-update' => function ($url, $model, $key) {
                        $options = [
                            'title' => Yii::t('yii', 'Update'),
                            'aria-label' => Yii::t('yii', 'Update'),
                            'data-pjax' => '0',
                        ];
                        return Html::a('<span class="glyphicon glyphicon-pencil"></span>', $url, $options);
                    },
                    'user-delete' => function ($url, $model, $key) {
                        $options = [
                            'title' => Yii::t('yii', 'Delete'),
                            'aria-label' => Yii::t('yii', 'Delete'),
                            'data-confirm' => Yii::t('yii', 'Are you sure you want to delete this item?'),
                            'data-method' => 'post',
                            'data-pjax' => '0',
                        ];
                        return Html::a('<span class="glyphicon glyphicon-trash"></span>', $url, $options);
                    },
                ]
            ],
        ],
    ]); ?>
    

    这样就OK了,但是代码变的超恶心,这不是我想要的,于是我重写了 yiigridActionColumn 增强了 template 的功能。
    类似 'template' => '{url-link:type}' 这样的,这里的 url-link 就是你的链接地址,type就是按钮类型,默认的3类按钮还在。

    例如:'template' => '{user-view:view} {user-update:update} {user-del:delete}'
    这样地址和样式都可以简单搞定,当然你依然可以自定义按钮,方法跟上面那个一样。

     
    <?= GridView::widget([
        'dataProvider' => $dataProvider,
        'filterModel' => $searchModel,
        'columns' => [
            ['class' => 'yiigridSerialColumn'],
            'id',
            'username',
            'email',
            [
                'class' => 'backendcomponentsActionColumn',
                'template' => '{user-view:view} {user-update:update} {user-del:delete} {user-diy-btn:diy}',
                'buttons' => [
                    // 自定义按钮
                    'diy' => function ($url, $model, $key) {
                        $options = [
                            'title' => Yii::t('yii', 'View'),
                            'aria-label' => Yii::t('yii', 'View'),
                            'data-pjax' => '0',
                        ];
                        return Html::a('<span class="glyphicon glyphicon-refresh"></span>', $url, $options);
                    },
                ]
            ],
        ],
    ]); ?>
    

    你只要增加一个 diy 类型的按钮就OK了,如果常用的话,你完全可以直接写到 backendcomponentsActionColumn 这里面。
    效果如下。

    这才是理想的状态,好了,下面给出这个 ActionColumn 代码吧。
    我是放在 backendcomponents 目录下,你也可以放在其他你自己喜欢的地方,命名空间改下就OK了。

     
    <?php
    namespace backendcomponents;
    
    class ActionColumn extends yiigridActionColumn
    {
    
        public $template = '{:view} {:update} {:delete}';
    
        /**
         * 重写了标签渲染方法。
         * @param mixed $model
         * @param mixed $key
         * @param int $index
         * @return mixed
         */
        protected function renderDataCellContent($model, $key, $index)
        {
            return preg_replace_callback('/\{([^}]+)\}/', function ($matches) use ($model, $key, $index) {
                list($name, $type) = explode(':', $matches[1].':'); // 得到按钮名和类型
    
                if (!isset($this->buttons[$type])) { // 如果类型不存在 默认为view
                    $type = 'view';
                }
    
                if ('' == $name) { // 名称为空,就用类型为名称
                    $name = $type;
                }
    
                $url = $this->createUrl($name, $model, $key, $index);
    
                return call_user_func($this->buttons[$type], $url, $model, $key);
            }, $this->template);
    
        }
    }
    

     <input type="button" class="btn btn-success" value="点击投票" >

    class="am-btn am-btn-secondary am-btn-xs"    class="am-icon-search"查看

     class="am-btn am-btn-warning am-btn-xs"    class="am-icon-edit"修改

    btn-warning 黄色 success 绿色

     plus 显示加号  ok 显示对号  remove 显示错号 eye-open 显示眼符号

    open 显示上传 pencil 显示铅笔 trash 显示删除 refresh 显示刷新

     

    分页显示:
    'pagination' =>[
            'pagesize' => '3',
      ]

    'pager' => ['activePageCssClass'=>'active','options'=>['class'=>'pagination pagination-default'],],

    想在某列td上应用样式。

    老写法是这样的

    复制代码
     <?= GridView::widget([
            'dataProvider' => $dataProvider,
            'layout' => "{items}
    {pager}
    {summary}",
            'summary' => '<p class="summary">当前显示第{begin} - {end}条,共{totalCount}条。</p>',
            'columns' => [
                ['class' => 'yiigridSerialColumn'],
                'name',
                [
                    // 看这里
                    'attribute' => 'propertyValuesString',
                    'format' => 'html',
                    'value' =>  function ($model, $key, $index, $column){
                        return '<div class="limit-width">'. $model->propertyValuesString .'</div>';
                    }
                ],    
                ......
    复制代码

    这样返回的html,td标签里面会套一层<div class="limit-width"></div>。

    如果才能将class应用在td上呢

    查了源码之后,可以这样:

    复制代码
             <?= GridView::widget([
          .......
    'columns' => [ ['class' => 'yiigridSerialColumn'], 'name',

    // 新增的代码
                [
                    'class' => 'yiigridColumn',
                    'contentOptions' => [
                        'class' => 'limit-width',
                    ],
                    'header' => '类目下的所有种类',
                    'content' => function ($model, $key, $index, $column){
                        return $model->propertyValuesString;
                    }
                ],
    复制代码

    也就是说。该列我需要用到 yii/grid/Column类。该类有个contentOptions属性。接收匿名函数或数组。数组就是属性名和属性值得键值对。渲染时该列包含一个th和多个td。th内容从header中取,td就是content。

    'rowOptions' => function($model, $key, $index, $grid) {
        return ['class' => $model->isEnabled ? 'label-green' : 'label-red'];
    }

    要添加复选框列到[[yiigridGridView]],如下添加它到[[yiigridGridView::$columns|columns]]配置:

    echo GridView::widget([
        'dataProvider' => $dataProvider,
        'columns' => [
            // ...
            [
                'class' => 'yiigridCheckboxColumn',
                // 在此配置其他属性
            ],
        ],
     

    用户可以点击复选框来选择网格的行。被选中的行可调用以下 JavaScript 代码获取:

    var keys = $('#grid').yiiGridView('getSelectedRows');
    // keys 是键名关联到选中行的数组

    数据筛选

    要筛选数据,表格视图需要一个模型从过滤的表单取得输入数据,并调整 dataprovider 的查询语句到期望的搜索条件。使用active records的惯例是建立一个搜索模型类继承活动记录类。然后用这个类定义搜索的验证规则和提供 search() 方法来返回 data provider 。

    要给 Post 模型添加搜索能力,可以创建 PostSearch ,如下所示:

    <?php
     
    namespace appmodels;
     
    use Yii;
    use yiiaseModel;
    use yiidataActiveDataProvider;
     
    class PostSearch extends Post
    {
        public function rules()
        {
            // 只有在 rules() 的字段才能被搜索
            return [
                [['id'], 'integer'],
                [['title', 'creation_date'], 'safe'],
            ];
        }
     
        public function scenarios()
        {
            // bypass 父类实现的scenarios()
            return Model::scenarios();
        }
     
        public function search($params)
        {
            $query = Post::find();
     
            $dataProvider = new ActiveDataProvider([
                'query' => $query,
            ]);
     
            // 加载搜索表单数据并验证
            if (!($this->load($params) && $this->validate())) {
                return $dataProvider;
            }
     
            // 通过添加过滤器来调整查询语句
            $query->andFilterWhere(['id' => $this->id]);
            $query->andFilterWhere(['like', 'title', $this->name])
                  ->andFilterWhere(['like', 'creation_date', $this->creation_date]);
     
            return $dataProvider;
        }
    }
     

    你可以在控制器使用这个方法来为表格视图获取 dataProvider :

    $searchModel = new PostSearch();
    $dataProvider = $searchModel->search($_GET);
     
    return $this->render('myview', [
        'dataProvider' => $dataProvider,
        'searchModel' => $searchModel,
    ]);
     

    然后在视图将 $dataProvider$searchModel 赋值给表格视图:

    echo GridView::widget([
        'dataProvider' => $dataProvider,
        'filterModel' => $searchModel,
    ]);
     

    使用模型关系

    当使用 GridView 显示活动记录(active records)时,你可能会遇到需要显示关联模型列的数值,比如想显示文章的作者的名字而不是他的 id。你可以在 columns 里面把这个属性名定义为 author.name ,当 Post 模型存在一个名为 author 的关系并且这个 author 模型拥有一个 name 属性,GridView将能显示作者的名字,不过缺省情况下,排序和过滤没有被启用。你得调整 PostSearch 模型(在最后部分介绍过)来添加这个功能。

    为了启用关联列的排序,你得联合(join)这个关联表,并添加排序规则到数据提供器(data provider)的 Sort 组件中:

    $query = Post::find();
    $dataProvider = new ActiveDataProvider([
        'query' => $query,
    ]);
     
    // 连接关联 `author` 表作为 `users` 表的一个关系
    // 并设置表别名为 `author`
    $query->joinWith(['author' => function($query) { $query->from(['author' => 'users']); }]);
    // 使关联列的排序生效
    $dataProvider->sort->attributes['author.name'] = [
        'asc' => ['author.name' => SORT_ASC],
        'desc' => ['author.name' => SORT_DESC],
    ];
     

    筛选也需要像上面那样调用 joinWith 。也可以定义可搜索特性和规则的列如下:

    public function attributes()
    {
        // 添加关联字段到可搜索特性
        return array_merge(parent::attributes(), ['author.name']);
    }
     
    public function rules()
    {
        return [
            [['id'], 'integer'],
            [['title', 'creation_date', 'author.name'], 'safe'],
        ];
    }
     

    然后在 search() 方法只须以 $query->andFilterWhere(['LIKE', 'author.name', $this->getAttribute('author.name')]);添加另一个过滤条件。

  • 相关阅读:
    简便的将DataSet导入到数据库中
    数据类型的小小研究:Access与SQL Server的数据类型
    【jxust acm 20120708】
    【D ECJTU_ACM 11级队员2012年暑假训练赛(2)】
    【hdu 2101 A + B Problem Too】
    【hdu 1014】
    【hdu 1164 Eddy's research I】
    【开始,安全编程】
    【hdu 1285 确定比赛名次】
    【hdu 1163 Eddy's digital Roots 】
  • 原文地址:https://www.cnblogs.com/jhy-ocean/p/5411032.html
Copyright © 2011-2022 走看看