I think this would stand as a solution to all laravel based ajax population with select 2.
Summary:
- Create a route for ajax return value
- Create a controller that obtains data from database/enum etc
- Return a generic select list item (Model) to a fill in a view
- Create a partial view with select Model you can use this with multiple items then.
- Create an ajax call to get relevant data
- Fill dom with ajax response and apply select2 on it.
- Optionally create a refresh method to reload items from database
Here is all the relevant code with explanation.
I would start with a route created in laravel for ajax call so it is defined like this
//DropDowns
Route::group([
'prefix'=>'dropdown',
],function(){
Route::get('/myObject/{selectedID?}/{terid?}/{sID?}',['as'=>'countryDropdown','uses'=>'Widgets\DropDownsController@myObjects']);
Route::get('/states/{selectedID?}/{regid?}/{sID?}',['as'=>'stateDropdown','uses'=>'Widgets\DropDownsController@states']);
});
You can have different structure but I prefer to keep dropdowns in one controller as they were only 4/5 and can be reused and remembered easily. Its not a hard rule where they are.
Then you create your controller to send json out.
public function states($selectedID=0,$regid=null,$sID='stateSelect',$sClass='stateSelect',$sName='stateSelect',$optClass='state',$single=true)
{
$dropdownhelper = new DropDownModel();
$branches = $dropdownhelper->getStates($regid); //This contains database logic to obtain states etc
$returnObject = $dropdownhelper->getObjectfromArray($branches, $selectedID, $sID, $sClass, $sName, $optClass);
//return response()->json($returnObject);
return view('layouts.twitterbootsrapshared._singleSelect',$returnObject);
}
These methods to obtain states are set in Models for example to get states you can have
// Get states method is like this
public function getStates($countryID = null)
{
$branches = [];
try {
if($countryID==null)
{
//Obtain All States
$states = DB::select('SELECT id,name FROM states ORDER BY name ASC');
}
else
{
$states = DB::select('SELECT id,name FROM states WHERE country_id = '.$countryID.' ORDER BY name ASC');
}
} catch (Exception $e) {
//Log that we are not able to obtain States
}
return $states;
}
I use a dropdown Model to obtain a dropdown object that I would use in view to populate it. This is simple method to take params and convert it to object ready for view.
/// DropdownModel has getObjectfromArray method like this
public function getObjectfromArray($arrayofElements,$selectedID=0,$selectID='',$selectClass='',$selectName='',$optionClass='')
{
$returnobject = [
'selectItems'=>$arrayofElements,
'selectedID'=>$selectedID,
'selectID'=>$selectID,
'selectClass'=>$selectClass,
'selectName'=>$selectName,
'optionClass'=>$optionClass
];
return $returnobject;
}
My view is a shared view in a twitterbootstrapshared folder under my layouts folder as you can see from controller call that it takes the model there and obtain a view like this
<select id="{{$selectID}}" class="{{$selectClass}}" name="{{$selectName}}">
@foreach ($selectItems as $option)
<option class="{{$optionClass}}" data-key="{{$option->id}}" data-name="{{$option->name}}"@if ($selectedID==$option->id) selected="selected" @endif value="{{$option->id}}">{{$option->name}}</option>
@endforeach
</select>
Next this contains the actual answer to your question when i need to call this dropdown anywhere on client side.
var getStates = function(){
var selectedID = $('#stateSelect option:selected').data('key');
if(!selectedID){selectedID=0;}
// I have another dropdown for selected country first but if you dont have you can ignore this. and pass nothing.
var selectedCountryID = $('#countrySelect option:selected').data('key');
if(!selectedCountryID){selectedCountryID=0;}
// Here i prepare what i need to send to ajax call
dataToSend={
'selectedID':selectedID,
'countryid':selectedCountryID==0?null:selectedCountryID,
'sID':"stateSelect",
};
// This is simple get request to that defined route
$.get('{{route('stateDropdown')}}',dataToSend,function(data){
if(data){
$('.stateContainer').html(data);
// Once obtained I will call select2 to populate it with data.
$('#stateSelect').select2({
placeholder:"Select a State",
width:'100%',
});
}
});
};
getStates();
My html on the page is like this in case you need to know what ID etc are in there
<div class="form-group">
<label class="control-label col-sm-2 font-noraml">States</label>
<div class=" col-sm-6 statesContainer">
</div>
<div class="col-sm-2"><button class="btn btn-sm btn-primary"><i class="fa fa-refresh refreshStates" title="Reload States"></i></button></div>
</div>
I have given a refresh button next to dropdown so in case it fails user can press refresh to obtain states again. Code for refesh button is this
$('.refreshState').on('click',function(){ getStates(); });
There are some assumptions and naming conventions that I follow but you are independent to do it your way.