以下方法且添加在控件相关文件中
1. table组件图片在修改时丢失
配置好的图片在修改时直接丢失,只能重新上传
方法如下:有一定弊端,图片配置不会丢失但也无法删除,可用额外字段作删除标记
$form->saving(function (Form $form) {
$images = $form->images;
foreach ($images as $key => &$item) {
if (isset($item['image']) && \request()->hasFile("images.{$key}.image")) {
unset($item['image']);
$item['image'] = \request()->file("images.{$key}.image")->store(config('filesystems.disks.public.directory.image'), 'public');
} else {
$item['image'] = $form->model()->images[$key]['image'] ?? "";
}
}
$form->model()->images = $images;
}
2.1. 表单输入框联动①:第二级随第一级切换而改变输入框类型
示例:如代码所示,需求为根据version切换显示channel_id还是coid
$form->select('version', '配置版本')
->options([0 => '渠道版', 1 => '企业版'])
->hideField(['channel_id', 'coid'], [[0 => 'channel_id'], [1 => 'coid']]);
$form->select('channel_id', '指定渠道')->options(Channel::all(['name', 'id'])->pluck('name', 'id'));
$form->select('coid', '指定企业')->options(Company::all(['id', 'name'])->pluck('name', 'id'));
我们只需要在select控件Select.php(App\Http\Admin\Extensions)中添加一下方法:
/**
* 通过选择值,展示或隐藏某些字段
* @param $fieldsGroup //参与隐藏或展示的字段组
* @param $condition //条件:当值等于X的时候展示Y字段 [value=>fields]
* @return $this
*/
public function hideField($fieldsGroup, $condition)
{
$fieldsGroupClass = [];
foreach ($fieldsGroup as $fieldName) {
$fieldClassName = '.' . trim($fieldName, '.');
$fieldsGroupClass[] = $fieldClassName;
}
$fieldClassName = implode(',', $fieldsGroupClass);
foreach ($condition as &$fieldName) {
$fieldName = array_map(function ($v) {
return '.' . $v;
}, $fieldName);
$fieldName = implode(',', $fieldName);
}
unset($fieldName);
$jsonCondition = json_encode($condition);
$script = <<getElementClassSelector()}",function(){
var _this=$(this);
var _val = _this.val();
var _condition=$jsonCondition
$("{$fieldClassName}").parents('.form-group').hide();
$("{$fieldClassName}").attr('disable',true)
if(_condition[_val]!=undefined){
var e =_condition[_val];
$(e).parents('.form-group').show();
$(e).attr('disable',false)
}
});
$("{$this->getElementClassSelector()}").trigger('change');
})
EOT;
Admin::script($script);
return $this;
}
2.2. 表单输入框联动②:第二级随第一级切换而展示/隐藏
示例:如代码所示,需求为根据auto_product切换展示/隐藏app_id,secret配置
$form->select('auto_product', '产品自增')
->options([1 => '手动添加产品', 0 => '自动同步产品'])
->hideField2(['appid', 'secret']);
$form->text('appid', 'appid');
$form->text('secret', 'secret');
方法如下:
/**
* 通过选择值,展示或隐藏某些字段 过去 现在 未来
* @param $fieldsGroup //参与隐藏/展示的字段
* @return $this
*/
public function hideField2($fieldsGroup)
{
$fieldsGroupClass = [];
foreach ($fieldsGroup as $fieldName) {
$fieldClassName = '.' . trim($fieldName, '.');
$fieldsGroupClass[] = $fieldClassName;
}
$script = <<getElementClassSelector()}",function(){
var _this=$(this);
var _val = _this.val();
if(_val == 1){
$("{$fieldsGroupClass[0]}").parents('.form-group').hide();
$("{$fieldsGroupClass[0]}").attr('disable',true);
$("{$fieldsGroupClass[1]}").parents('.form-group').hide();
$("{$fieldsGroupClass[1]}").attr('disable',true);
}
if(_val == 0){
$("{$fieldsGroupClass[0]}").parents('.form-group').show();
$("{$fieldsGroupClass[0]}").attr('disable',false);
$("{$fieldsGroupClass[1]}").parents('.form-group').show();
$("{$fieldsGroupClass[1]}").attr('disable',false);
}
});
$("{$this->getElementClassSelector()}").trigger('change');
})
EOT;
Admin::script($script);
return $this;
}
小结:
上面两种不同情况都很简单,一些简单的js,jQuery知识。有额外情况只需仿照以上代码,观察表单的dom结构做出相应修改即可。
3. 二级联动初始化问题
select二级联动在修改/添加界面的时候无法展示已有的配置,即使第一级有默认值
方法:重写联动select的load方法,添加以下代码$("{$this->getElementClassSelector()}").trigger('change');
. 即在页面加载时就触发一次change事件,加载出我们已有的配置
方法如下:
/**
* Load options for other select on change.
*
* @param string $field
* @param string $sourceUrl
* @param string $idField
* @param string $textField
*
* @return $this
*/
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'),
]);
$script = <<getElementClassSelector()}");
$(document).on('change', "{$this->getElementClassSelector()}", function () {
var select_value = $(this).attr('data-value');
var target = $(this).closest('.fields-group').find(".$class");
$.get("$sourceUrl",{q : this.value}, function (data) {
target.find("option").remove();
var data_value = target.attr("data-value");
var values = data_value.split(',');
$(target).select2({
placeholder: $placeholder,
allowClear: $allowClear,
data: $.map(data, function (d) {
d.id = d.$idField;
d.text = d.$textField;
console.log(String(d.id));
if($.inArray(String(d.id), values) != -1){
d.selected = true;
}
return d;
})
}).trigger('change');
});
});
$("{$this->getElementClassSelector()}").trigger('change');
EOT;
Admin::script($script);
return $this;
}
4. 复制当前数据并修改后添加
public function copy($id)
{
return Admin::content(function (Content $content) use ($id) {
$content->header('新建员工中心');
$form = $this->form()->edit($id);
$form->builder()->setMode();
$form->setAction(route('employee.store'));
$content->body($form);
});
}
表格
$grid->actions(function (Grid\Displayers\Actions $actions) {
$url = route('employee.copy', ['id' => $actions->row->id]);
$actions->append("");
});