Laravel-admin 中 table,select 控制元件額外需求

愛餘生發表於2020-01-20

以下方法且新增在控制元件相關檔案中

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 = <<<EOT
$(function(){
    $(document).on('change',"{$this->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 = <<<EOT
$(function(){
    $(document).on('change',"{$this->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 = <<<EOT
$(document).off('change', "{$this->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("<a href={$url}><i class='fa fa-copy'></i></a>");
 });
本作品採用《CC 協議》,轉載必須註明作者和本文連結

愛餘生

相關文章