首先,官方文檔中給出的具體實現方法:
select 聯動
select
組件支持父子關係的單向聯動:
$form->select('province')->options(...)->load('city', '/api/city');
$form->select('city');
其中load('city', '/api/city');
的意思是,在當前select的選項切換之後,會把當前選項的值通過參數q
, 調用接口/api/city
,並把api返回的數據填充爲city選擇框的選項,其中api /api/city
返回的數據格式必須符合:
[
{
"id": 9,
"text": "xxx"
},
{
"id": 21,
"text": "xxx"
},
...
]
控制器action的代碼示例如下:
public function city(Request $request)
{
$provinceId = $request->get('q');
return ChinaArea::city()->where('parent_id', $provinceId)->get(['id', DB::raw('name as text')]);
}
坦白講,看不是太明白
首先,'/api/city' 這個接口文件怎麼寫? 只說了格式要求,沒說具體怎麼寫,直接創建aip目錄,然後添加city類嗎?
其次,public function city(Request $request) 這個跟上面的load方法是怎麼關聯起來的,而且方法內還有個get('q')參數,不理解
網上找了半天,也沒找到個能說得清除的,最後沒辦法,只能硬着頭皮看看源碼
主要看load()方法
public function load($field, $sourceUrl, $idField = 'id', $textField = 'text', bool $allowClear = true)
{
if (Str::contains($field, '.')) {
$field = $this->formatName($field);
$class = str_replace(['[', ']'], '_', $field);
} else {
$class = $field;
}
$placeholder = json_encode([
'id' => '',
'text' => trans('admin.choose'),
]);
$strAllowClear = var_export($allowClear, true);
$script = <<<EOT
$(document).off('change', "{$this->getElementClassSelector()}"); //移除所有change事件
$(document).on('change', "{$this->getElementClassSelector()}", function () { //添加所有change事件
var target = $(this).closest('.fields-group').find(".$class"); // 從當前元素開始沿 DOM 樹向上獲取對象
//構造一個GET 請求到sourceUrl頁面並取回結果 同時傳遞q參數,值是當前select選中的option的value值
//這個方法很重要,子類select就是通過這個方法,通過路由找到對應控制器'GoodController@activityList',並獲取值的
$.get("$sourceUrl",{q : this.value}, function (data) {
target.find("option").remove();
$(target).select2({
placeholder: $placeholder,
allowClear: $strAllowClear,
data: $.map(data, function (d) {
d.id = d.$idField;
d.text = d.$textField;
return d;
})
}).trigger('change');
});
});
EOT;
Admin::script($script);
return $this;
}
分析:
1、load()方法 有兩個參數:
第一個是下級select的name
第二個是獲取數據的路由,通過訪問該路由到達指定的控制器中,在控制器中獲取數據
這裏要注意的是load中的路由url不能寫錯 我這裏是 load('subid', '/admin/activityList'); 之前寫/activityList一直獲取不到數據
protected function form()
{
$form->select('supid', __('大類名稱'))->options(
Topcate::all()->where('state','=','1')
->pluck('name','id'))
->load('subid', '/admin/activityList');
$form->select('subid','小類名稱');
…………
}
2、添加路由: 在Admin/routes.php 中添加load方法中的路由指向 這裏是指定到本控制器中的方法
Route::group([
…………
], function (Router $router) {
…………
$router->get('activityList','GoodController@activityList');
});
3、load()方法中,構造了一個GET請求並帶參數q的值,通過路由找到控制器activityList方法,
所以,最後我們要在activityList方法中通過q值獲取對應的子類數據
public function activityList(Request $request){
$projectId = $request->get('q');
return Subcate::where('supid',$projectId)->get(['id', DB::raw('name as text')]);
}
最後實現二級聯動效果
最後,要注意的是,使用select->load()方法,必須在當前控制器中引入 Request 和 DB類
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
//如果要用到admin JSON組件,還需要引入Admin類
use Encore\Admin\Admin;
以上是個人分析結果,如有錯誤,敬請執教!