LaravelRUS / SleepingOwlAdmin

🦉 Administrative interface builder for Laravel (Laravel admin)
http://sleepingowladmin.ru/
MIT License
805 stars 217 forks source link

setColumnFilters error #410

Closed macedodebrito closed 7 years ago

macedodebrito commented 7 years ago

hello.

when i try to add "setColumnFilters" to my "datatablesAsync", i get this error:

Argument 1 passed to BaseColumnFilter::apply() must implement interface NamedColumnInterface, instance of Column\Custom given, called in Display\Extension\ColumnFilters.php on line 196 and defined

the code i added was this one:

    $display->setColumnFilters([

        AdminColumnFilter::date()->setPlaceholder('por Data')->setFormat('d.m.Y'),
        AdminColumnFilter::text()->setPlaceholder('por PP'),
        AdminColumnFilter::text()->setPlaceholder('por Nº de Série'),
        AdminColumnFilter::text()->setPlaceholder('por Produto'),
        null,
        AdminColumnFilter::text()->setPlaceholder('por Obs'),
        null
    ]);

Anyone with this error fixed?

Thanks

butschster commented 7 years ago

Show display columns

macedodebrito commented 7 years ago
    $display->setColumnFilters([

        AdminColumnFilter::date()->setPlaceholder('por Data')->setFormat('d.m.Y'),
        AdminColumnFilter::text()->setPlaceholder('por PP'),
        AdminColumnFilter::text()->setPlaceholder('por Produto'),
        AdminColumnFilter::text()->setPlaceholder('por Quantidade'),
        AdminColumnFilter::text()->setPlaceholder('por Operador'),
        AdminColumnFilter::text()->setPlaceholder('por Obs'),
        null
    ]);

    $display->setColumns([
                AdminColumn::datetime('created_at')
                ->setLabel('Efectuado em')
                ->setWidth('100px')
                ->setHtmlAttribute('class', 'text-center')
                ->setFormat('d.m.Y H:i'),
                AdminColumn::custom()->setLabel('Nº Pedido de Produção')->setCallback(function ($instance) {
                            $new_color = "";
                            $pp = Request::where('id', $instance->request_pp['id'])->first();
                            $dump = RequestUser::where('id', $instance->id)->first();
                            if ($dump->published < 0) {
                                $new_color = "bg-red";
                            }
                            return "<div class=\"$new_color text-center\">$pp->pp</div>";
                        })
                ->setWidth('100px')
                ->setHtmlAttribute('class', 'bg-gray text-center'),
                AdminColumn::custom()
                ->setLabel('Produto')
                ->setWidth('100px')
                ->setCallback(function ($instance) {
                            $product_name = Product::where('id', $instance->request_pp['product_id'])->first();
                            $new_color = "";
                            $pp = Request::where('id', $instance->request_pp['id'])->first();
                            $dump = RequestUser::where('id', $instance->id)->first();
                            if ($dump->published < 0) {
                                $new_color = "bg-red";
                            }
                            return "<div class=\"$new_color text-center\">$product_name->name</div>";
                        }),
                AdminColumn::custom()
                ->setLabel('Quantidade')
                ->setWidth('100px')
                ->setHtmlAttribute('class', 'bg-success text-center')
                ->setCallback(function ($instance) {
                            $total = Request::where('id', $instance->request_id)->first();
                            $efectuados = RequestUser::where('request_id', $instance->request_id)->sum('value');
                            $missing = $total->value - $efectuados;

                            if ($missing < 0) {
                                $new_color = "bg-red";
                            } else if ($missing == 0) {
                                $new_color = "bg-success";
                            } else {
                                $new_color = "bg-success";
                            }

                            $new_color = "";
                            $pp = Request::where('id', $instance->request_pp['id'])->first();
                            $dump = RequestUser::where('id', $instance->id)->first();
                            if ($dump->published < 0) {
                                $new_color = "bg-red";
                            }

                            return "<div class=\"$new_color text-center\">$instance->value</div>";
                        }),
                AdminColumn::custom()
                ->setLabel('Operador')
                ->setWidth('10%')
                ->setHtmlAttribute('class', 'bg-warning text-center')
                ->setCallback(function ($instance) {
                            $new_color = "";
                            $pp = Request::where('id', $instance->request_pp['id'])->first();
                            $dump = RequestUser::where('id', $instance->id)->first();
                            if ($dump->published < 0) {
                                $new_color = "bg-red";
                            }
                            $go = User::where('id', $instance->user_id)->first()->bigname;
                            return "<div class=\"$new_color text-center\">$go</div>";
                        }),
                AdminColumn::custom()
                ->setLabel('Observações')
                ->setCallback(function ($instance) {
                            $new_color = "";
                            $pp = Request::where('id', $instance->request_pp['id'])->first();
                            $dump = RequestUser::where('id', $instance->id)->first();
                            if ($dump->published < 0) {
                                $new_color = "bg-red";
                            }
                            return "<div class=\"$new_color text-center\">$instance->obs</div>";
                        }),
                AdminColumn::custom()
                ->setLabel('Status')
                ->setWidth('5%')
                ->setCallback(function ($instance) {
                            // warning 
                            // check = 1
                            // remove
                            // user-times = -1
                            $default_html_tag = "#pendente";
                            $default_icon = "fa-circle-o-notch fa-spin fa-2x";
                            $role_check = 0;
                            $role_id = Role::where('name', 'cnc')->first();
                            if (count(DB::table('role_user')->where('role_id', $role_id->id)->where('user_id', Auth::user()->id)->first()) > 0) {
                                $role_check = 1;
                            }
                            switch ($instance->published) {
                                case 1:
                                    $default_icon = "fa-check fa-2x";
                                    return "<i class=\"fa $default_icon\"></i>";
                                    break;
                                case -1:
                                    $default_icon = "fa-user-times fa-2x";
                                    $default_html_tag = "#removing";
                                    if ($role_check > 0) {
                                        return "<a id=\"$instance->id\" class=\"accept_product\" href=\"$default_html_tag\"><i class=\"fa $default_icon\"></i></a>";
                                    } else {
                                        return "<i class=\"fa fa-user-times fa-2x\"></i>";
                                    }
                                    break;
                                default:
                                    if ($role_check > 0) {
                                        return "<a id=\"$instance->id\" class=\"accept_product\" href=\"#removing_fast\"><i class=\"fa fa-user-times fa-2x\"></i></a> <i class=\"fa $default_icon\"></i>";
                                    } else {
                                        return "<a href=" . url('/admin/wood/open') . "><i class=\"fa $default_icon\"></i></a>";
                                    }
                                    break;
                            }
                        })
    ]);

    return $display;
macedodebrito commented 7 years ago

when i see debug console, i get this:

403 forbidden

http://localhost/app/public/admin/requests/cnc_history/async?draw=1&columns%5B0%5D%5Bdata%5D=0&columns%5B0%5D%5Bname%5D=&columns%5B0%5D%5Bsearchable%5D=true&columns%5B0%5D%5Borderable%5D=true&columns%5B0%5D%5Bsearch%5D%5Bvalue%5D=&columns%5B0%5D%5Bsearch%5D%5Bregex%5D=false&columns%5B1%5D%5Bdata%5D=1&columns%5B1%5D%5Bname%5D=&columns%5B1%5D%5Bsearchable%5D=true&columns%5B1%5D%5Borderable%5D=false&columns%5B1%5D%5Bsearch%5D%5Bvalue%5D=&columns%5B1%5D%5Bsearch%5D%5Bregex%5D=false&columns%5B2%5D%5Bdata%5D=2&columns%5B2%5D%5Bname%5D=&columns%5B2%5D%5Bsearchable%5D=true&columns%5B2%5D%5Borderable%5D=false&columns%5B2%5D%5Bsearch%5D%5Bvalue%5D=&columns%5B2%5D%5Bsearch%5D%5Bregex%5D=false&columns%5B3%5D%5Bdata%5D=3&columns%5B3%5D%5Bname%5D=&columns%5B3%5D%5Bsearchable%5D=true&columns%5B3%5D%5Borderable%5D=false&columns%5B3%5D%5Bsearch%5D%5Bvalue%5D=&columns%5B3%5D%5Bsearch%5D%5Bregex%5D=false&columns%5B4%5D%5Bdata%5D=4&columns%5B4%5D%5Bname%5D=&columns%5B4%5D%5Bsearchable%5D=true&columns%5B4%5D%5Borderable%5D=false&columns%5B4%5D%5Bsearch%5D%5Bvalue%5D=&columns%5B4%5D%5Bsearch%5D%5Bregex%5D=false&columns%5B5%5D%5Bdata%5D=5&columns%5B5%5D%5Bname%5D=&columns%5B5%5D%5Bsearchable%5D=true&columns%5B5%5D%5Borderable%5D=false&columns%5B5%5D%5Bsearch%5D%5Bvalue%5D=&columns%5B5%5D%5Bsearch%5D%5Bregex%5D=false&columns%5B6%5D%5Bdata%5D=6&columns%5B6%5D%5Bname%5D=&columns%5B6%5D%5Bsearchable%5D=true&columns%5B6%5D%5Borderable%5D=false&columns%5B6%5D%5Bsearch%5D%5Bvalue%5D=&columns%5B6%5D%5Bsearch%5D%5Bregex%5D=false&columns%5B7%5D%5Bdata%5D=7&columns%5B7%5D%5Bname%5D=&columns%5B7%5D%5Bsearchable%5D=true&columns%5B7%5D%5Borderable%5D=false&columns%5B7%5D%5Bsearch%5D%5Bvalue%5D=&columns%5B7%5D%5Bsearch%5D%5Bregex%5D=false&order%5B0%5D%5Bcolumn%5D=0&order%5B0%5D%5Bdir%5D=desc&start=0&length=10&search%5Bvalue%5D=&search%5Bregex%5D=false&_=1484563501241

macedodebrito commented 7 years ago

Can i "reopen" this?

Now that error is fixed but i cant see the column filters.

The table is visible, with Async working, but $display->setColumnFilters is not displaying anything neither if i add BEFORE $display->setColumns or AFTER it.

do i missed something?

Thanks.

butschster commented 7 years ago

Try to run php artisan vendor:publish --tag=assets --force and update browser assets shift + F5

macedodebrito commented 7 years ago

nothing works.

when i run composer update, i have it setted to do that command everytime.

refresh didnt worked either :(

macedodebrito commented 7 years ago

another issue:

i did a new table with datatablesAsync, and seems its working, so i will check in the above one what is wrong.

about the new Async table, it have issues anyway, like this one:

http://imgur.com/byIHXOk

As you can see here, everything is OK, but when i SEARCH, nothing happens:

http://imgur.com/hzSUW3m

My code is this one:

$model->onDisplay(function () {
    $display = AdminDisplay::datatablesAsync()->paginate(25);
    $display->setApply(function($query) {
        $query->orderBy('name', 'asc');
    });

    $display->setHtmlAttribute('class', 'table-info table-hover');

    $display->with('series');

    $display->setFilters([
        AdminDisplayFilter::related('serie_id')->setModel(Serie::class)
    ]);

    $display->setColumns([
        AdminColumn::text('id')->setLabel('#')->setWidth('30px'),
        AdminColumn::link('name')->setLabel('Nome do Produto'),
        AdminColumn::link('code')->setLabel('Código'),
        AdminColumn::link('points')->setLabel('Pontuação'),
        AdminColumn::text('series.name')->setLabel('Série')->append(AdminColumn::filter('serie_id'))
    ]);

    $display->setColumnFilters([
        null,
        AdminColumnFilter::text()->setPlaceholder('por Produto'),
        AdminColumnFilter::text()->setPlaceholder('por Quantidade'),
        AdminColumnFilter::text()->setPlaceholder('por Operador'),
        AdminColumnFilter::text()->setPlaceholder('por Obs'),
    ]);

    return $display;
});

Any ideas?

butschster commented 7 years ago

Can you create github repo with configured demo app and your code?

Try it AdminColumnFilter::text()->setPlaceholder('por Produto')->setOperator('contains') https://github.com/LaravelRUS/SleepingOwlAdmin/blob/development/src/Traits/SqlQueryOperators.php#L18

By default uses operator equal

macedodebrito commented 7 years ago

ok this worked. thanks @butschster .

about the repo, just let me test something else and i will give you feedback.

just to have it here, for everyone, i asked for 2 extra infos:

changing the filters to BEFORE table: $display->getColumnFilters()->setPlacement('panel.heading');

(extra info: panel.heading, panel.footer, after.panel, before.panel, table.header, table.footer )

AND removing the default search input: $display->setDatatableAttributes(['searching' => false]);

thanks Alexandr.

macedodebrito commented 7 years ago

ok, latest update fixed the header, showing up.

but now i cant, even with ->setOperator, put the filters working.

i think this is because i used custom() without using the $instance value ?

example:

AdminColumn::custom()
                    ->setLabel('Observações')
                    ->setCallback(function ($instance) {
                                $new_color = "";
                                $pp = Request::where('id', $instance->request_pp['id'])->first();
                                $dump = RequestUser::where('id', $instance->id)->first();
                                if ($dump->published < 0) {
                                    $new_color = "bg-red";
                                }
                                return "<div class=\"$new_color text-center\">$instance->obs</div>";
                            }),

is possible? if i use this code, it works:

$display->setColumns([ AdminColumn::text('id')->setLabel('#')->setWidth('30px'), AdminColumn::link('name')->setLabel('Nome do Produto'), AdminColumn::link('code')->setLabel('Código'), AdminColumn::link('points')->setLabel('Pontuação'), AdminColumn::text('series.name')->setLabel('Série')->append(AdminColumn::filter('serie_id')) ]);

    $display->setColumnFilters([
        null,
        AdminColumnFilter::text()->setPlaceholder('por Produto')->setOperator('contains'),
        AdminColumnFilter::text()->setPlaceholder('por Quantidade'),
        AdminColumnFilter::text()->setPlaceholder('por Operador'),
        AdminColumnFilter::text()->setPlaceholder('por Obs'),
    ]);
macedodebrito commented 7 years ago

the bug is here: $display->getColumnFilters()->setPlacement('panel.heading');

if i add this, the filters search will not work.

again, i think if we have 2 tables in same view, somehow, those filters wont be visible (its the old bug)

macedodebrito commented 7 years ago

ok i tested again:

2 bugs:

1) custom() with a something like this, wont work: return "<div class=\"$new_color text-center\">$instance->obs

";

he is not searching the $instance->obs (it seems), dunno if its because the extra div inside (i dont know how to change the column-row color without this trick)

2) if more than one table in same view, default filter wont show up, and if we use something like: $display->getColumnFilters()->setPlacement('panel.heading');

he wont search, even with a simple: AdminColumn::text('points')->setLabel('Points'), + AdminColumnFilter::text()->setPlaceholder('por points')->setOperator('contains'),

any idea?

thanks

macedodebrito commented 7 years ago

this wont work even with custom() and a normal return:

    $display->setColumns([
        AdminColumn::text('id')->setLabel('#')->setWidth('30px'),
        AdminColumn::link('name')->setLabel('Nome do Produto'),
        AdminColumn::link('code')->setLabel('Código'),
        //AdminColumn::link('points')->setLabel('Pontuação'),
        AdminColumn::custom()
                ->setLabel('points')
                ->setWidth('100px')
                ->setHtmlAttribute('class', 'bg-success text-center')
                ->setCallback(function ($instance) {
                            return $instance->points;
                        }),
        AdminColumn::text('series.name')->setLabel('Série')->append(AdminColumn::filter('serie_id'))
    ]);

    $display->setColumnFilters([
        null,
        AdminColumnFilter::text()->setPlaceholder('por Produto')->setOperator('contains'),
        AdminColumnFilter::text()->setPlaceholder('por Quantidade'),
        AdminColumnFilter::text()->setPlaceholder('por points')->setOperator('contains'),
        AdminColumnFilter::text()->setPlaceholder('por Obs'),
    ]);

as you can see, the "points" have a custom() Column, but the filter is not able to find anything.

if i comment that custom() and uncomment the previous line, it will work.

i was trying to "bypass" this bug, but with custom() i just cant :D

ghost commented 7 years ago

Custom columns has no filter interface. In here can be implemented some logic what have be disposed in filter method. Need time for thinking about best way for resolve that problem.

P.S. u use queries in callback method - that will be executed each of row. that's no good.

macedodebrito commented 7 years ago

Hello @aios .

yes, i changed that (those queries @ callback) to Model functions.

But, if i simply do this, it wont work anyway:

$display->setColumns([
            AdminColumn::text('id')->setLabel('#')->setWidth('30px'),
            AdminColumn::link('name')->setLabel('Nome do Produto'),
            AdminColumn::link('code')->setLabel('Código'),
//            AdminColumn::link('points')->setLabel('Pontuação'),
            AdminColumn::custom()
                    ->setLabel('points')
                    ->setWidth('100px')
                    ->setHtmlAttribute('class', 'bg-success text-center')
                    ->setCallback(function ($instance) {
                                return $instance->points;
                            }),
            AdminColumn::text('series.name')->setLabel('Série')->append(AdminColumn::filter('serie_id'))
        ]);

        $display->setColumnFilters([
            null,
            AdminColumnFilter::text()->setPlaceholder('por Produto')->setOperator('contains'),
            AdminColumnFilter::text()->setPlaceholder('por Quantidade')->setOperator('contains'),
            AdminColumnFilter::text()->setPlaceholder('por points')->setOperator('contains'),
            AdminColumnFilter::text()->setPlaceholder('por Obs')->setOperator('contains'),
        ]);

as you can see, its a normal CALLBACK, with a simple return. Filter wont work.

You already told Custom columns has no filter interface. BUT, what about the normal "search" ?

Search input is not working with DatatablesAsync(). How can we use it, like normal Datatables() ? That would be perfect, and column filters could be avoided ( or adding custom filter search support :D )

ghost commented 7 years ago

@macedodebrito I am sorry - but you dont understand how it working... i try explain.

setColumns and setColumnFilters will intersect and combine data by keys. So if it find instanceof Custom when exec filter interface thhrow exception because cant find Interface for your logic or something implemented in your callback. Its happend because every search go to backend - and Custom column counts logic after selecting data from DB. We cant find them on backend.

Again we can talk about as you say "Normal search" in Datatables (not Async) Datatables counting all objects as rows and load it to table making one query and hide objects by javascript So all data in table and filter working because datatable implement storage on frontend. In here you custom logic (counted) that data can filter without exception.

macedodebrito commented 7 years ago

i understand the procedure.

another bug i found is: i cant order by date with Async.

ghost commented 7 years ago

ref #412 ref #116