Livewire - Dependant Dropdown select - laravel

I have created a dependant dropdown with livewire like this:
class CreateAppointment extends Component
{
public $doctorCategories;
public $doctors;
public $selectedDoctorCategory = NULL;
public function mount(){
$this->doctorCategories = Doctor_Categories::all();
$this->doctors = collect();
}
public function updatedSelectedDoctorCategory($doctor_type_ID)
{
if(!is_null($doctor_type_ID)){
$this->doctors = Doctor_Categories::with('doctors')->find($doctor_type_ID);
}
}
}
And this is in my blade file:
<div class="form-group row">
<label for="doctor_categories" class="col-md-4 col-form-label text-md-right">Doctor Categories</label>
<div class="col-md-6">
<select wire:model="selectedDoctorCategory" class="form-control">
<option value="">Choose category</option>
#foreach($doctorCategories as $cat)
<option value="{{ $cat->id }}">{{ $cat->doctor_category }}</option>
#endforeach
</select>
</div>
</div>
#if (!is_null($selectedDoctorCategory))
<div class="form-group row">
<label for="doctor" class="col-md-4 col-form-label text-md-right">Doctor</label>
<div class="col-md-6">
<select class="form-control" name="doctor_id">
<option value="" selected>Choose Doctor</option>
#foreach($doctors->doctors as $doctor)
<option value="{{ $doctor->id }}">{{ $doctor->name }}</option>
#endforeach
</select>
</div>
</div>
#endif
</div>
It works well but when i select "Choose category" again it throws an error saying attempted to read property doctors on null.How can i avoid this?

The issue here is, that livewire does not apply the TrimStrings and ConvertEmptyStringsToNull middlewares on its requests. This is by design and is not a bug. It can be reintroduced (see the comments to the linked issue) but I advise caution doing so. With select it should work fine, but with input it can mess things up.
Instead of checking for is_null, check for empty and you should be fine.

Related

Laravel Livewire : livewire multiple root elements detected

I'm currently developing a website using laravel livewire
The website has a multi-site form page, and there's a dynamic dropdown on the inside of that multi-site form page
The problem is when the form is filled, it won't store the data into the database
When i do inspect the website there's an error that read :livewire multiple root elements detected
How do i fix this??
Livewire model :
<?php
namespace App\Http\Livewire;
use Livewire\Component;
use App\Models\Kredit;
use App\Models\Biaya;
use App\Models\Produk;
use App\Models\Promo;
use App\Models\Motorcycle;
use App\Models\MotorcycleBrand;
use App\Models\Domisili;
class KreditMulti extends Component
{
public $brand_id;
public function render()
{
$domisilis = Domisili::all();
// $motorcycles = Motorcycle::all();
// $motorcycle_brands = MotorcycleBrand::all();
//for the dynamic dropdown
if($this->brand_id){
$motorcycle_brands = MotorcycleBrand::where('motorcycle_id', $this->brand_id)->get();
} else {
$motorcycle_brands = [];
}
return view('livewire.kredit-multi',
['domisilis'=>$domisilis])
->withMotorcycles(Motorcycle::all())
->with('motorcycle_brands', $motorcycle_brands);
}
}
The livewire blade php :
<div class="form-group row">
<label for="motorcycle" class="col-md-4">Merek motor</label>
<div class="col-md-6">
<select wire:model="brand_id" class="form-control">
<option value="" selected>Choose Motor</option>
#foreach ($motorcycles as $m)
<option value="{{$m->id}}">{{$m->motorcycle_name}}</option>
#endforeach
</select>
</div>
</div>
<br>
#if (count($motorcycle_brands) > 0)
<div class="form-group row">
<label for="motorcycle_brand" class="col-md-4 col-form-label text-md-right">Jenis Motor</label>
<div class="col-md-6">
<select class="form-control" name="motorcycle_brand_id">
<option value="" selected>Choose the motor version</option>
#foreach ($motorcycle_brands as $motor)
<option value="{{$motor->id}}" wire:key="motorcycle_brand{{$motor->id}}">{{$motor->motorcycle_brand_name}}</option>
#endforeach
</select>
</div>
</div>
#endif
<br>
all livewire components must be start with a <div> and end with a </div>.
actually you must wrap the whole <div> and </div> s into a single <div></div>
Your blade code has several roots
1.- <div class="form-group row"....>
2.- <br>
3.- #if (count($motorcycle_brands) > 0)...#endif
4.- <br>
Enclose all that stuff in a single root
<div>
<div class="form-group row"....>
<br>
#if (count($motorcycle_brands) > 0)...#endif
<br>
</div>
The error is as exact as it can be. A Livewire component simply can only have a single root element. Instead, you're adding 2, including 2 breaks.
Wrap the whole component into a single <div></div>, and then it should be fixed.
public $motorcycle_brands,$domisilis,$brand_id,$motorcycles;
public function render()
{
$this->domisilis = Domisili::all();
$this->motorcycles = Motorcycle::all();
if($this->brand_id){
$this->motorcycle_brands = MotorcycleBrand::where('motorcycle_id', $this->brand_id)->get();
} else {
$this->motorcycle_brands = [];
}
return view('livewire.kredit-multi');
}
Blade
#if (count($motorcycle_brands) > 0)
<div class="form-group row">
<label for="motorcycle_brand" class="col-md-4 col-form-label text-md-right">Jenis Motor</label>
<div class="col-md-6">
<select class="form-control" wire:model="brand_id">
<option value="" selected>Choose the motor version</option>
#foreach ($motorcycle_brands as $motor)
<option value="{{$motor->id}}">{{$motor->motorcycle_brand_name}}</option>
#endforeach
</select>
</div>
</div>
#endif

I want to get data to the dropdown by using another dropdown in the same page

I have a dropdown on my page to load districts. And I have another dropdown to load Divisions according to that selected district. The below code I have got all the divisions. But I want only the divisions according to the selected districts. How can I do?
#php
$districtAll=\App\District::all();
#endphp
<div class="row">
<label class="col-md-4 control-label" for="district">9. District</label>
<div class="col-md-8">
<select name="district">
<option type="text" class="detail-wp" value="">Select District</option>
#foreach($districtAll as $all)
<option value="{{$all->DISTRICT_ID}}">{{$all->DISTRICT}} </option>
#endforeach
</select>
</div>
</div>
<br>
#php
$getDsAll=\App\DsDivision::all();
#endphp
<div class="row">
<label class="col-md-4 control-label" for="ds_division">10. DS Division</label>
<div class="col-md-8">
<select name="ds_division" class="form-control">
<option type="text" class="detail-wp" value=""></option>
#foreach($getDsAll as $all)
<option value="{{$all->DIVISION_ID}}">{{$all->DIVISION}} </option>
#endforeach
</select>
</div>
</div>
You can do it using ajax request:
$('select[name=district]').on('change', function(){
$districtId = $(this).val();
$.get('/division/district/'+$districtId).done(function(res){
$.each(res, function (key, value) {
$('select[name=ds_division]').append(`<option value='` + value.id + `'>` + value.name +`</option>`);
});
});
to make this working you will need a route like
Route::get("/division/district/{district}", "DivisionController#getByDistrictId");
DivisionController#getByDistrictIdwill be
public function getByDistrictId($district)
{
return Division::where('district_id',$district)->get();
}
this code just to give you an idea of how you can do it.

show data of nested foreach loop in two different Select Tag in laravel

I have two Model(Category,Brand) are relate with one to many relation(hasMany) in laravel, Like category hasMany brands. now i want to display brand data in one select tag and category model data in another select tag.
Here is my Controller code
$category=Category::with('brands')->get();
return view('product.add')->with('category',$category);
Here is my view blade.
<div class="form-group">
<select name="category_id" class="input">
<option value="">Select Main Category</option>
#foreach($category as $category)
<option value="{{$category->id}}">{{$category->name}}</option>
#endforeach
</select>
</div>
<div class="form-group">
<select name="brand_id" class="input">
#foreach($brands->brands as $brand)
<option value="{{$brand->id}}">{{$brand->name}}</option>
#endforeach
</select>
</div>
its not working
You can do something simple like this:
<div class="form-group">
<select name="category_id" class="input">
<option value="">Select Main Category</option>
#foreach($category as $cat)
<option value="{{$cat>id}}">{{$cat->name}}</option>
#endforeach
</select>
</div>
<div class="form-group">
<select name="brand_id" class="input">
#foreach($category as $cat)
#foreach($cat->brands as $brand)
<option value="{{$brand->id}}" category="{{$cat->id}}">{{$brand->name}}</option>
#endforeach
#endforeach
</select>
</div>
and you need to show only the brands for the selected option using javascript(jquery)
$('[name="category_id"]').on('change',function() {
if($(this).val() != '') {
$('[name="brand_id"] option').hide();
$('[name="brand_id"] option[category="'+$(this).val()+'"]').show();
} else {
$('[name="brand_id"] option').show();
}
});

how to validate select box in laravel (without using JS)

<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label">Publication Status</label>
<div class="col-sm-10">
<select name="publicationStatus" class="form-control">
<option value="">Select Manufacturer</option>
<option value="1">Published</option>
<option value="0">Unpublished</option>
</select>
<span class="text-danger">{{$errors->has('publicationStatus')? $errors->first('publicationStatus'):''}}</span>
</div>
</div>
my controller
public function storeManufacturer(Request $request){
$this->validate($request,[
'manufacturerName'=>'required',
'manufacturerDescription'=>'required',
'publicationStatus'=>'required',
]);
above 'manufacturerName' & 'manufacturerDescription' is working but publicationStatus is not validate in the same way.Maybe the reason is that contain multiple value.
You could check data of $request with dd() in your controller firstly:
dd($request->publicationStatus);

Can't make multiple select in registration form

I use the basic registration form but I want to add a multiple select, a User can have multiple Skills and select them when he register.
My problem is that when I select multiples values Laravel only take the last one, so I search on the web for a solution and they say to add [] after my class name, so this is what I do :
<div class="form-group row">
<div class="col-md-6">
<?php $competences = \App\Competence::all(); ?>
<select name="competences[]" multiple="" class="form-control">
<option value="" selected disabled style="display:none">choose your school</option>
#foreach ($competences as $competence)
<option value="{{ $competence->id }}">{{ $competence->name }}</option>
#endforeach
</select>
</div>
</div>
But now, when I submit the form the page reload and stay in the register form, and the user is not register... I don't know what to do, anyone of you have a solution ?
Here is how I check the competences in my registerController
$competences = $data['competences'];
foreach ($competences as $comp){
$user->competences()->save(Competence::find($comp));
}
Use multiple="multiple" OR just multiple in blade.php:
<div class="form-group row">
<div class="col-md-6">
<?php $competences = \App\Competence::all(); ?>
<select name="competences[]" class="form-control" multiple>
<option value="" selected disabled style="display:none">choose your school</option>
#foreach ($competences as $competence)
<option value="{{ $competence->id }}">{{ $competence->name }}</option>
#endforeach
</select>
</div>
</div>
then in your controller, verify that you're actually getting the data in the form of an array by just printing $data
return $data;

Resources