Reputation: 829
I have a page with doctors listing. All the doctors belongs to specific category: gynecology, surgery, urology etc.
How can I filter them with a select drop down without using submit button? I know this is possible to achieve with Ajax, but I need help.
Here's my code:
DoctorsController
public function doctorsList() {
$doctors = Doctor::orderBy('id', 'desc')->paginate(20);
$categories = Category::all();
return view('doctors-list', compact('doctors', 'categories'));
}
doctors-list.blade.php
<div class="filter text-center">
<select name="category_id">
<option value="all">All</option>
@foreach($categories as $category)
<option value="{{ $category->id }}">{{ $category->title }}</option>
@endforeach
</select>
</div>
@foreach($doctors as $doctor)
<div class="article">
<div class="row">
<div class="col-sm-3">
<div class="image"><a href="{{ route('doctor', $doctor->slug) }}"><img width="260" src="{{ Storage::url($doctor->image) }}" /></a></div>
</div>
<div class="col-sm-9 right">
<div class="title"><h3>{{ $doctor->title }}</h3></div>
<div class="body">{!! strip_tags(str_limit($doctor->body, 300)) !!}</div>
<div class="more"><a href="{{ route('doctor', $doctor->slug) }}">More></a></div>
</div>
</div>
</div>
@endforeach
Route:
Route::get('/doctors', 'DoctorsController@doctorsList')->name('doctorsList');
Migrations (two separate files):
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateDoctorsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('doctors', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('doctors');
}
}
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateDoctorTranslationsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('doctor_translations', function (Blueprint $table) {
$table->increments('id');
$table->integer('doctor_id')->unsigned();
$table->string('locale')->index();
// The actual fields to store the content of your entity. You can add whatever you need.
$table->string('title');
$table->string('slug')->unique();
$table->string('image');
$table->text('body');
$table->integer('category_id');
$table->string('status');
$table->integer('user_id');
$table->unique(['doctor_id', 'locale']);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('doctor_translations');
}
}
Models: Doctor.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Dimsav\Translatable\Translatable;
class Doctor extends Model
{
use Translatable;
public $translatedAttributes = ['title', 'slug', 'image', 'body', 'category_id','status', 'user_id'];
public function category() {
return $this->belongsTo('App\Category');
}
}
DoctorTranslation.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Cviebrock\EloquentSluggable\Sluggable;
class DoctorTranslation extends Model
{
use Sluggable;
public $timestamps = false;
/**
* Return the sluggable configuration array for this model.
*
* @return array
*/
public function sluggable()
{
return [
'slug' => [
'source' => 'title',
'onUpdate' => true
]
];
}
}
Right now with this code I'm displaying all the doctors and I have created the Select box that gets the categories from the database.
How can I filter them when I choose a different category from the drop down?
I'm using Laravel 5.5
Upvotes: 0
Views: 1952
Reputation: 24276
You can use a query parameter to filter the doctors by category. This would be the updated controller method:
public function doctorsList(Request $request)
{
$query = (new Doctor)->newQuery();
$selectedCategory = $request->get('category_id', 'all');
if (is_numeric($selectedCategory )) {
$query->whereTranslation('category_id', $selectedCategory);
}
$doctors = $query->orderBy('id', 'desc')->paginate(20);
$categories = Category::all();
return view('doctors-list', compact('doctors', 'categories', 'selectedCategory'));
}
And the blade template would be something like:
<form action="{{route('doctorsList')}}" method="get">
<div class="filter text-center">
<select name="category_id" onchange="this.form.submit()">
<option value="all">All</option>
@foreach($categories as $category)
<option value="{{ $category->id }}" {{$category->id == $selectedCategory ? 'selected' : ''}}>{{ $category->title }}</option>
@endforeach
</select>
</div>
</form>
@foreach($doctors as $doctor)
<div class="article">
<div class="row">
<div class="col-sm-3">
<div class="image"><a href="{{ route('doctor', $doctor->slug) }}"><img width="260" src="{{ Storage::url($doctor->image) }}" /></a></div>
</div>
<div class="col-sm-9 right">
<div class="title"><h3>{{ $doctor->title }}</h3></div>
<div class="body">{!! strip_tags(str_limit($doctor->body, 300)) !!}</div>
<div class="more"><a href="{{ route('doctor', $doctor->slug) }}">More></a></div>
</div>
</div>
</div>
@endforeach
Of course, you can put the onchange handler somewhere in your js files instead of doing it inline.
I considered you named the doctors listing route as doctors.list
Also, if you use this solution, you should be aware to add the category query parameter to the pagination links too.
Upvotes: 3
Reputation: 1663
Here is my solution in this solution you will not require any server call
just give id to the <div class="article">
give id as docs-categoryid-doctorid
now on your <select name="category_id" onchange="showhidedocs();">
function showhidedocs(){
var cat=$('#category_id').val();
if(cat!="all"){
$('[id^=docs-]').hide();
var temp="[id^=docs-"+cat+']';
$(temp).show();
}else{
$('[id^=docs-]').show();
}
}
Upvotes: 2