Como agregar select2 como filtro de un gridview utilizando Ajax para la búsqueda de elementos

Como agregar select2 como filtro de un gridview utilizando Ajax para la búsqueda de elementos

En este manual se muestra cómo agregar un select2 de kartik utilizando ajax como filtro de un gridview, el cual permite buscar conforme se teclea.





Requisitos

Recomendamos esta solución sólo si el volumen de datos a mostrar en el select es muy grande -- mayor a 1,000 registros -- ya que cualquier cantidad mayor a estos hará más lenta la carga de la página. Si lo que quiere es sólo implementar un select2 simple le recomendamos revisar ésta página


Para implementar esta solución deberas instalar y configurar los siguientes librerias


Select2

No se cubre en este manual la instalación del componente select2, si tienes duda de cómo instalarlo puedes seguir la documentación de la página: 

https://github.com/kartik-v/yii2-widget-select2

Gridview de kartik

No se cubre en este manual la instalación del componente Gridview de karitk, si tienes duda de cómo instalarlo puedes seguir la documentación de la página: 

https://github.com/kartik-v/yii2-grid


Implementación

Para la implementación vamos a necesitar hacer cambios a 3 elementos

1-. Model Search
2.- Vista
3.- Controller


1. Modificaciones a model Search

Identifique el model Search que está relacionado a su GridView, será necesario hacerlo los siguientes cambios.

Agregar método público

Dentro de las propiedades debe agregar un método público, puede llamarlo como usted desee éste será utilizado posteriormente.



    public $usuarioAfectado;

 
Agregar el metodo rules

Identifique el metodo rules() del modelo search y agregue el nombre del parámetro dentro del arreglo que se identifica como "safe".


    
 /**
     * {@inheritdoc}
     */
    public function rules() {
        return [
            [
            .....
                [
                    ...
                    'usuarioAfectado',
                    ..
                ],
                'safe'],
.....

}


 
Agregar unión del campo a filtrar

El filtro que utilice debe de estar relacionado mediante algún campo de la base de datos y a su vez de los modelos, por lo tanto debe agregar la unión con la tabla relacionada en el query del Model Search. 

Es importánte verificar que la unión entre las tablas también esté en el modelo principal el cual se está utilizando en el GridView



    
     /**
     * Creates data provider instance with search query applied
     *
     * @param array $params
     *
     * @return ActiveDataProvider
     */
    public function search($params) {
        $query = Ticket::find()
        ->joinWith('usuarioAsignado');
        // add conditions that should always apply here

        $dataProvider = new ActiveDataProvider([
            'query' => $query,
            'sort' => ['defaultOrder' => ['id' => SORT_DESC]]
        ]);


 
Agregar el filtro en la sección de where


Dentro de todos los modelSearch hay una sección donde debe de agregar algunas lineas, ejemplo: 



    
     /**
     * Creates data provider instance with search query applied
     *
     * @param array $params
     *
     * @return ActiveDataProvider
     */
    public function search($params) {
         .......
        $query->andFilterWhere(['like','usuario_afectado.nombre',$this->usuarioAfectado]);



 
Observe que estamos utilizando la clausula "like" y el segúndo parámetro es el nombre del campo que estamos haciendo referencia para el filtro y el tercer parámetro hace referencia al método de la clase ModelSearch. 

Con esos cambios terminamos con los cambios al ModelSearch

2. Modificaciones a la vista


Agregar librerías necesarias

Deberá de agregar las siguientes librerías que serán necesarias:



    use kartik\grid\GridView;
    use yii\helpers\Url;    
    use yii\web\JsExpression;

 
Y debe agregar el modelo correspondiente al filtro que estamos agregando. 

Agregar select2 

Deberá de agregar el filtro dentro de las columnas del Gridview




GridView::widget([
                            'dataProvider' => $dataProvider,
                            'filterModel' => $searchModel,

                            },
                            'columns' => [
                              ....... 


                                [
                                    'attribute' => 'usuario_afectado_id',
                                    'value' => 'usuarioAfectado.nombre',
                                    'label' => 'Afectado',
                                    'filterType' => GridView::FILTER_SELECT2,
                                    'filterWidgetOptions' => [
                                        'initValueText' => $filteredUsuarioAfectado?$filteredUsuarioAfectado->nombre:null ,
                                        'pluginOptions' => [
                                            'allowClear' => true,
                                            'closeOnSelect' => true,
                                            'minimumInputLength' => 3,
                                            'ajax' => [
                                                'url' => Url::to(['usuario-afectado/usuarioslist']),
                                                'dataType' => 'json',
                                            ],
                                        ],
                                    ],
                                    'filterInputOptions' => ['placeholder' => '...'],
                                ],


                            ......
                            ],
                        ]);


 
A continuación agregamos algunas observaciones.

attribute: Debe de agregar el campo de la llave foranea que se relaciona la tabla del modelo principal.
value: Debe ser el nombre de la relación que existe dentro del modelo principal y la tabla de la cual estamos utilizando el filtro, ejemplo: 

 // Modelo principal


    /**
     * Gets query for [[UsuarioAfectado]].
     *
     * @return \yii\db\ActiveQuery
     */
    public function getUsuarioAfectado()
    {
        return $this->hasOne(UsuarioAfectado::className(), ['id' => 'usuario_afectado_id']);
    }

 
label: Sera el nombre de la columna que se mostrara.

filterType=> GridView::FILTER_SELECT2: Este campo va tal cual y es el que hace referencia a la utilización de dicha libreria llamada Select2.

filterWidgetOptions: Es un parámetro utilizado para pasar parámetros adicionales.

initValueText: Este parámetro permite cargar un parámetro inicial, es importánte agregar algunas las siguientes líneas al inicio de la vista para mantener seleccionado el nombre del elemento ya que al ser una llamada desde Ajax no interactua completamente con el SearchModel. 

Agregar estas líneas al inicio del la vista


$filteredUsuarioAfectadoId = ArrayHelper::getValue( Yii::$app->getRequest()->getQueryParam('TicketSearch'), 'usuario_afectado_id' );


$filteredUsuarioAfectado = $filteredUsuarioAfectadoId ? UsuarioAfectado::findOne($filteredUsuarioAfectadoId ) : null;

 
La primera linea busca en los parámetros del modelSearch.
La segunda linea busca el modelo relacionado con el ID que obtiene del parámetro del ModelSearch, si el parámetro es null entonces devolvera un null, en el caso cotrario cuando se selecciona un item del select2 entonces devuelve el modelo correspondiente el cual se establece como valor inicial del search. 

pluginOptions: Establece parámetros adicionales. 

'allowClear' => true : Permite borrar el select2 para hacer una nueva búsqueda.

'closeOnSelect' => true : Permite cerrar despues de seleccionar el item.

minimumInputLength: Este parámetro es el que define el mínimo de caracteres a escribir para que se lance la búsqueda via ajax.

ajax: Define carácteristicas para utilizar ajax. 

url' => Url::to(['usuario-afectado/usuarioslist']) Esta linea es la que manda a llamar al controller que realiza la búsqueda a la base de datos.

'dataType' => 'json' : Esta propiedad se define para que la respuesta del ajax sea tratada en formato JSON.

3. Crear un nuevo controller

Para que el ajax funcione se necesita un controller el cual será ejecutado desde el select2 y es el que dará respuesta cuando el usuario busque dentro del select2.

El controller pueden quedar en cualquier parte, sólo debe se asegurarse de tener acceso desde cualquiera de las vistas donde será utlizado.

El siguiente es un ejemplo del controller que puede utilizar.



 
    public function actionUsuarioslist($q = null) {
        Yii::$app->response->format = Response::FORMAT_JSON;
        $out = ['results' => ['id' => '', 'text' => '']];
        if (!is_null($q)) {          
            $query = UsuarioAfectado::find()
                    ->select('id, nombre AS text')
                    ->where(['like','nombre',$q])
                    ->limit(10)
                    ->asArray()
                    ->all();
            
            $out['results'] = $query;
        }
        return $out;
    }


 


Referencias:


Ejemplo en linea de la implementación:
https://stackoverflow.com/questions/48931161/kartik-select2-in-gridview-filter-show-id-instead-of-name/

Documentacion Select2 de kartik:
https://demos.krajee.com/widget-details/select2


Comentarios

Aprende Yii2


Lo más Visto

Tutorial de implementación de calendario de rango de fechas con Karkit en gridView

Guía rápida para uso de widget kartik para select para formulario

Cómo incluir una vista dentro de un modal

Google Plus desaparecerá el 4 de Abril de 2019

Crear fomulario HTML con checkbox sin Active Record

hostinger

ventana bienvenida