Open omarkadd opened 5 years ago
PRs welcome
as for me iam not really good enough to pull this myself so if any one else would help that would be great
any update regarding this feature of filtration? @fletch3555
No update. Nobody has built it yet
It is a good thing that there are now thoughts in this direction, because it was an absolute no no when I brought it up in the slack channel
I hope this comes up soon. I wish to have some more time to do a PR for this.
However, maybe a palliative I created for myself may be useful for someone in the mean time: https://github.com/damms005/laravel-model-export
Is there any update on having associated data being searchable? And should this be merged with #3595 ?
Hi, I made a quick fix for multiple field search, It does work, but it needs work. I'll put a bit more code that it would be easier to see where what goes. WORKS ONLY WITH SERVER SIDE PAGINATION, AND BRAKES NON SERVER SIDE PAGINATION Look for: ------->>>>>
class VoyagerBaseController extends BaseVoyagerBaseController
{
public function index(Request $request)
{
// GET THE SLUG, ex. 'posts', 'pages', etc.
$slug = $this->getSlug($request);
// GET THE DataType based on the slug
$dataType = Voyager::model('DataType')->where('slug', '=', $slug)->first();
// Check permission
$this->authorize('browse', app($dataType->model_name));
$getter = $dataType->server_side ? 'paginate' : 'get';
// $search = (object) ['value' => $request->get('s'), 'key' => $request->get('key'), 'filter' => $request->get('filter')];
$searchNames = [];
if ($dataType->server_side) {
$searchable = SchemaManager::describeTable(app($dataType->model_name)->getTable())->pluck('name')->toArray();
$dataRow = Voyager::model('DataRow')->whereDataTypeId($dataType->id)->get();
foreach ($searchable as $key => $value) {
$field = $dataRow->where('field', $value)->first();
$displayName = ucwords(str_replace('_', ' ', $value));
if ($field !== null) {
$displayName = $field->getTranslatedAttribute('display_name');
}
$searchNames[$value] = $displayName;
}
}
$orderBy = $request->get('order_by', $dataType->order_column);
$sortOrder = $request->get('sort_order', $dataType->order_direction);
$usesSoftDeletes = false;
$showSoftDeleted = false;
// Next Get or Paginate the actual content from the MODEL that corresponds to the slug DataType
if (strlen($dataType->model_name) != 0) {
$model = app($dataType->model_name);
if ($dataType->scope && $dataType->scope != '' && method_exists($model, 'scope'.ucfirst($dataType->scope))) {
$query = $model->{$dataType->scope}();
} else {
$query = $model::select('*');
}
// Use withTrashed() if model uses SoftDeletes and if toggle is selected
if ($model && in_array(SoftDeletes::class, class_uses_recursive($model)) && Auth::user()->can('delete', app($dataType->model_name))) {
$usesSoftDeletes = true;
if ($request->get('showSoftDeleted')) {
$showSoftDeleted = true;
$query = $query->withTrashed();
}
}
// If a column has a relationship associated with it, we do not want to show that field
$this->removeRelationshipField($dataType, 'browse');
//------->>>>>
//------->>>>>
$search = $request->all();
if (count($search) > 0) {
foreach ($search as $key => $val) {
if (!strpos($key, 'relationship') && $val != null) $query->where($key, 'LIKE', '%' . $val . '%');
}
// $query->where($search->key, $search_filter, $search_value);
}
//------->>>>>
//------->>>>>
This goes to bread browse.blade.php Simple form with submit
<thead>
<tr>
<form method="get" class="form-search">
@if($showCheckboxColumn)
<th>
<input type="checkbox" class="select_all">
</th>
@endif
//------->>>>>
//------->>>>>
@foreach($dataType->browseRows as $key => $row)
<th>
@if ($isServerSide)
<a href="{{ $row->sortByUrl($orderBy, $sortOrder) }}">
@endif
{{ $row->getTranslatedAttribute('display_name') }}
@if ($isServerSide)
@if ($row->isCurrentSortField($orderBy))
@if ($sortOrder == 'asc')
<i class="voyager-angle-up pull-right"></i>
@else
<i class="voyager-angle-down pull-right"></i>
@endif
@endif
</a>
@endif
@if ($isServerSide)
<input type="text" name="{{$row->field}}" value="{{ !empty($search[$row->field ]) ? $search[$row->field ] : ''}}">
@endif
</th>
@endforeach
//------->>>>>
//------->>>>>
<button class="btn btn-info btn-lg" type="submit">
<i class="voyager-search"></i>
</button>
</form>
<th class="actions text-right">{{ __('voyager::generic.actions') }}</th>
</tr>
</thead>
UPDATE pagination links
{{ $dataTypeContent->appends(
array_merge(
$search,
[
'order_by' => $orderBy,
'sort_order' => $sortOrder
]
)
)->links() }}
UPDATE I store the id of the relation, so it works for me. Right now I'm building a prototype of my app, so I didnt test it fully. I will test it on the go
if (count($search) > 0) {
foreach ($search as $key => $val) {
if (
$val != null
&& $key != 'page'
&& $key != 'sort_order'
&& $key != 'order_by'
&& strpos($key, 'relationship')
) {
$infoAboutColumn = $dataRow->where('type', '=','relationship')->where('field', '=', $key)->first();
$relationshipTableModel = $infoAboutColumn->details->model; // Model to search in for the ralation
$relationshipTableLabel = $infoAboutColumn->details->label; // column name in the relation table
$itemFromRelation = $relationshipTableModel::where($relationshipTableLabel, 'LIKE', '%' . $val .'%')->first(); // item from relation table
$columnNameInYoureTable = $infoAboutColumn->details->column; // Name of the column, that you are ralationing with
$idFromRelationTable = $itemFromRelation->id;
$query->where($columnNameInYoureTable, 'LIKE', '%' . $idFromRelationTable . '%');
} else {
if (
!strpos($key, 'relationship')
&& $val != null
&& $key != 'page'
&& $key != 'sort_order'
&& $key != 'order_by'
) {
$query->where($key, 'LIKE', '%' . $val . '%')->get();
}
}
}
}
BelongsTo ServerSide Search #3595 filtration #4216
Version information
@vyyytenis Thanks a lot for the well explained code! It was a great help so i made a few changes in my own project. It's an ugly code I KNOW but it Works with server side pagination without breaking non-server side pagination, & no changes needed in the browse blade. Hope it helps in some way..!
Steps :
Use a custum controller like in Voyager-docs : Using custom Controllers
In the new controller created copy index method from VoyagerBaseController
In line 95 make these changes
if ($search->value != '' && $search->key && $search->filter) {
$search_filter = ($search->filter == 'equals') ? '=' : 'LIKE';
$search_value = ($search->filter == 'equals') ? $search->value : '%' . $search->value . '%';
// changes
$searchKeyType = $dataRow->where('display_name', '=', $searchNames[$search->key])->pluck('type')->toArray();
if (in_array('relationship', $searchKeyType)) {
$infoAboutColumn = $dataRow->where('type', '=', 'relationship')->where('display_name', '=', $searchNames[$search->key])->first();
$relationshipTabledetails = $infoAboutColumn->details;
$relationshipTableModel = $relationshipTabledetails->model;
$relationshipTableLabel = $relationshipTabledetails->label;
$relatedmodel = app($relationshipTableModel);
$additional_attributes = $relatedmodel->additional_attributes ?? [];
$value = $search->value;
if (in_array($relationshipTableLabel, $additional_attributes)) {
$idFromRelationTable = $relatedmodel->all();
$idFromRelationTable = $idFromRelationTable->filter(function ($relatedmodel) use ($value, $relationshipTabledetails) {
return stripos($relatedmodel->{$relationshipTabledetails->label}, $value) !== false;
});
$idFromRelationTable = $idFromRelationTable->pluck('id')->toArray();
} else {
$idFromRelationTable = $relationshipTableModel::where($relationshipTableLabel, 'LIKE', '%' . $search->value . '%')->pluck('id');
}
$columnNameInYourTable = $infoAboutColumn->details->column;
$query->whereIn($columnNameInYourTable, $idFromRelationTable);
}
else{
$query->where($search->key, $search_filter, $search_value);
}
}
// end changes
Version information
Description of feature
datatables provide a multiple filtration to the table which cannot be done in voyager. filtration could re-draw tables as the user need.(like the images attached) adding printing to tables and exporting as excel or pdf or word
Proposed solution
add support for multiple filtration and advanced search add exporting feature to the tables
Alternatives considered
providing a clear way to do it manually
Additional context