Laravel-datatables: ¿Cómo buscar en una columna generada por addColumn?

Creado en 3 ago. 2015  ·  22Comentarios  ·  Fuente: yajra/laravel-datatables

Primero, gran trabajo para este increíble paquete.

Tengo un pequeño problema:

Agregué una nueva columna personalizada en su archivo de demostración: ... / eloquent / add-edit-remove-column, quiero buscar / filtrar esa columna, pero aparece un error en el navegador cuando ingreso todo.

¿Existe una solución para buscar / filtrar en una columna personalizada y luego agregar un texto de entrada de búsqueda para cada columna de la tabla, incluso para custom_column?

Error en la consola de FireBug:

  <span class="exception_message">SQLSTATE[42S22]: Column not found: 1054 Champ
 &#039;new_column&#039; inconnu dans where clause (SQL: select count(*) as aggregate from (select &#039
;1&#039; as row_count from `users` where (LOWER(`id`) LIKE %b% or LOWER(`name`) LIKE %b% or LOWER(`email
`) LIKE %b% or LOWER(`created_at`) LIKE %b% or LOWER(`updated_at`) LIKE %b% or LOWER(`new_column`) LIKE
 %b%)) count_row_table)</span>

Código del controlador:

    public function getAddEditRemoveColumnData()
    {
        $users = User::select(['id', 'name', 'email', 'password', 'created_at', 'updated_at']);

        return Datatables::of($users)
                                 ->addColumn('new_column' , 'ABC')
                                  ->make(true)
    }

Código de Javascript:

    $('#users-table').DataTable({
        processing: true,
        serverSide: true,
        ajax: '{{ url("eloquent/add-edit-remove-column-data") }}',
        columns: [
            {data: 'id', name: 'id'},
            {data: 'name', name: 'name'},
            {data: 'email', name: 'email'},
            {data: 'created_at', name: 'created_at'},
            {data: 'updated_at', name: 'updated_at'},
            {data: 'new_column', custom: 'new_column', orderable: true, searchable: true}
        ]
    });

Comentario más útil

@marioene , no puede buscar en addColumn si los datos no son de la base de datos. Una solución para esto es agregar la columna en su declaración de selección como se muestra a continuación. No es necesario usar addColumn .

$users = User::select([
'id', 'name', 'email', 'password', 'created_at', 'updated_at',
DB::raw("'ABC' as new_column")
]);

Nota: Es posible que deba escribir un filterColumn para que funcione. Solo asegúrese de que el sql generado esté funcionando y también debería funcionar con el paquete.

Todos 22 comentarios

@marioene , no puede buscar en addColumn si los datos no son de la base de datos. Una solución para esto es agregar la columna en su declaración de selección como se muestra a continuación. No es necesario usar addColumn .

$users = User::select([
'id', 'name', 'email', 'password', 'created_at', 'updated_at',
DB::raw("'ABC' as new_column")
]);

Nota: Es posible que deba escribir un filterColumn para que funcione. Solo asegúrese de que el sql generado esté funcionando y también debería funcionar con el paquete.

El cierre debido a la inactividad y la solución alternativa sugerida anteriormente deberían solucionar el problema. ¡Gracias!

@yajra Seguí tu sugerencia de agregar primero una columna calculada usando 'seleccionar' (en Controlador)

$staffData = Staff::select('id', 'staff_id', \DB::raw('concat(first_name, " ", middle_name, " ", last_name) as full_name'), 'department_name', 'status');

Luego agregué un filtro personalizado (en Controlador)

$dt = Datatables::of($staffData);
return $dt->filterColumn('full_name', function($query, $keyword) {
            $query->whereRaw("CONCAT(first_name, ' ', middle_name, ' ', last_name) like ?", ["%{$keyword}%"]);
        })->make(true);

Cuando cargo por primera vez la página, la tabla de datos se representa correctamente cuando busco utilizando el cuadro de texto de entrada de búsqueda global, se arroja un error

Ajax error. http://datatables.net/tn/7

¿Puede decirme dónde podría estar cometiendo un error?

@ AshishGupta001 intente inspeccionar la solicitud ajax usando las herramientas de desarrollo de Chrome o Firebug. Le dará una pista sobre la causa del problema. Lo más probable es que se trate de un problema de excepción de SQL.

@yajara Gracias por tu rápida respuesta.
Al implementar la búsqueda global de una columna 'calculada' (en mi caso, 'nombre_completo') tomé referencia a
1) Número 168: https://github.com/yajra/laravel-datatables/issues/168
2) Ejemplo: https://datatables.yajrabox.com/eloquent/post-column-search

Antes de agregar la 'filterColumn ()' personalizada para mi tabla de datos, recibía una excepción de SQL quejándose por la falta de la columna 'full_name' en la tabla. Luego agregué el siguiente código para agregar un filtro personalizado para la columna 'calculada' (en mi caso, 'nombre_completo') como se muestra a continuación

$dt->filterColumn('full_name', function($query, $keyword) {
       $query->whereRaw("CONCAT(staff.first_name, ' ', staff.middle_name, ' ', staff.last_name) like ?", ["%{$keyword}%"]);
});

return $dt->make(true);

Ahora obtengo el siguiente error en el registro

mb_strtolower() expects parameter 1 to be string, object given en archivo ......./vendor/laravel/framework/src/Illuminate/Support/Str.php#162

Aprecie si puede ayudar a solucionar este problema.

@ AshishGupta001 ¿Qué versión estás usando? Tu código me parece bien.

@yajra Gracias por confirmar. Las versiones son las siguientes

PHP - 5.5.38-3
Laravel - 5.0.34
Tablas de datos - yajra / laravel-datatables-oracle: ^ 6.3 (como en composer.json)

Parece que en 'getOrMethod' en la clase Helper, se lanza una excepción ya que está tratando de convertir para reducir un "clouser" pasado como parámetro de entrada.

public static function getOrMethod($method) {
   if (! Str::contains(Str::lower($method), 'or')) {
      return 'or' . ucfirst($method);
   }
      return $method;
}

'$ método' es un clouser pasado function($query, $keyword) , como se muestra a continuación

Closure {#864
  reflection: """
    Closure [ <user> public method App\Http\Controllers\{closure} ] {\n
      @@ /var/www/html/XYZ/app/Http/Controllers/StaffHistoryController.php 310 - 313\n
    \n
      - Parameters [2] {\n
        Parameter #0 [ <required> $query ]\n
        Parameter #1 [ <required> $keyword ]\n
      }\n
    }\n
    """
}

Aunque no pude resolver el problema al que me enfrenté, pude encontrar la forma de solucionar este caso de uso específico. Gracias por las sugerencias disponibles aquí.

Vista: tenga lo siguiente en la vista dentro de la etiqueta de secuencia de comandos

{ data: 'full_name', name: 'full_name', searchable: false },
{ data: 'first_name', name: 'first_name', searchable: true, visible: false },
{ data: 'middle_name', name: 'middle_name', searchable: true, visible: false },
{ data: 'last_name', name: 'last_name', searchable: true, visible: false }

Controlador: obtenga el primer nombre, etc. en la consulta SQL junto con el resto de los valores de la columna.

@ AshishGupta001 me alegro de que lo hayas descubierto. Eso es lo que solía hacer también desde la versión Laravel 4.2. 👍

@ AshishGupta001 ¡ Buena solución!

@yajra ¿Podemos buscar una columna agregada usando addColumn cuyos datos provienen de la base de datos pero no estamos agregando esta columna en el JS?

¿O deberíamos agregarlo al JS y hacerlo invisible pero con capacidad de búsqueda?

Algunas formas en las que puedo pensar:

  1. Agréguelo a js y hágalo invisible y que se pueda buscar como dijo.
  2. Utilice filterColumn para manejar manualmente la búsqueda de la columna agregada.
  3. Declararlo de esta manera:
{data: 'added_column', name: 'actual_column_name'}

Gracias por tu rápida respuesta @yajra

Ya estaba probando la segunda solución, pero noté que esta columna agregada no se considera en la consulta.

Alguna idea ?

Asegúrese de no agregar searchable: false en esa columna.

Así es como agregué la columna ->addColumn('company_name', function($deal) { return $deal->company_name; })

Y la consulta de búsqueda global como $dataTable->filterColumn('company_name', 'where', "like", ["%$keyword%"]);

¿Podemos pasar searchable: false en el backend?

searchable: false está en el lado del cliente js.

Por cierto, ¿qué versión estás usando?

Ah, vale. Así que todavía necesitamos usar la primera forma que mencionaste, con esta forma.
Estoy usando v6.17.0

Tengo el mismo problema que @ AshishGupta001, desafortunadamente, el truco del lado del cliente no lo corta ya que la columna no se puede ordenar.
He explorado la alternativa filterColumn pero no pude hacer que funcione también.
usando "yajra / laravel-datatables-oracle": "~ 9.0"

método del controlador:

    public function getAccounts(Request $request)
    {
        if ($request->ajax()) {
            $accounts = Account::with('current_marketer')->select([
                '*',
                DB::raw("CONCAT(accounts.lastname,' ',accounts.firstname) as fullname"),
            ]);
            return Datatables::of(Account::query()->with('current_marketer'))
            ->addColumn('marketer', function(Account $account){
                return $account->current_marketer->name;
            })
            ->addColumn('fullname', function($account){
                return '<a href="'.route('account.clients.show', $account->account_number).'" class="hover:underline" target="_blank">'. $account->fullname.'</a>';
            })
            ->filterColumn('fullname', function($query, $keyword) {
                $sql = "CONCAT(accounts.lastname,' ',accounts.firstname)  like ?";
                $$query->whereRaw($sql, ["%{$keyword}%"]);
            })
            ->rawColumns(['fullname'])
            ->editColumn('created_on', function(Account $account) {
                return Carbon::parse($account->created_on)->format('jS F, Y');
            })
            ->toJson();
        }
        return view('datatables.accounts.index');
    }

Blade js:

 $('#accounts-table').DataTable({
          "processing": true,
          "serverSide": true,
          "ajax": '{{ route('accounts.get') }}',
          "columns": [
            { data: "id" },
            { data: "account_number" },
            { data: 'fullname'},
            { data: "marketer" },
            { data: "created_on" },
          ]
        });

Excepción: cuando se intenta buscar u ordenar:

yajraIssue

pues resulta que el problema con esa excepción fue culpa mía; Tenía un signo doble '$$' dentro de mi método filterColumn.
yajra_issue_fix_1

Sin embargo, eso no solucionó mi problema de clasificación. Todavía necesito saber:

  1. cómo hacer que la columna se pueda ordenar
  2. cómo buscar y ordenar columnas relacionadas otra mirada a los documentos borró esto para mi caso de uso

@ seewhy17 puede usar orderColumn para una clasificación compleja. Sin embargo, en su caso, ordenar por fullname ya funcionaría de fábrica.

@ seewhy17 puede usar orderColumn para una clasificación compleja. Sin embargo, en su caso, ordenar por fullname ya funcionaría de fábrica.

Bueno, no fue así, supongo que el método filterColumn entra en conflicto con un evaluador del modelo que básicamente hace lo mismo ... Realmente no lo sé.
Para saber, logré que funcione agregando un name: lastname al js, por lo que filtra por apellido y el método filterColumn es redundante

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

jgatringer picture jgatringer  ·  3Comentarios

FilipeBorges1993 picture FilipeBorges1993  ·  3Comentarios

techguydev picture techguydev  ·  3Comentarios

kamrava picture kamrava  ·  3Comentarios

ahmadbadpey picture ahmadbadpey  ·  3Comentarios