DcatAdmin 擴充套件: 自定義表單(動態表單)

Slowlyo發表於2022-06-27

效果

DcatAdmin 自定義元件: 自定義表單(動態表單)

DcatAdmin 自定義元件: 自定義表單(動態表單)

DcatAdmin 自定義元件: 自定義表單(動態表單)

DcatAdmin 擴充套件: 自定義表單(動態表單)

功能

自定義組合表單項, 適用於需要自定義表單項的場景

安裝

composer require slowlyo/dcat-diy-form

GitHub

使用

// form() 中
$form->diyForm('field_name');
// detail() 中
$show->field('filed_name')->diyForm();

擴充套件項

為了方便擴充套件, 元件中提供了一些方法
預設元件型別包括:

  • input
  • textarea
  • radio
  • checkbox
  • select
  • upload-image
  • upload-vedio

themeColor()

// themeColor() 方法可以設定元件的主題色, 預設取Dcat的主題色(primary)
// 引數為色號或者顏色名稱, 如果不生效, 那就是識別不了
$form->diyForm('field_name')->themeColor('red');

subComponentType()

// subComponentType() 方法可以移除指定的元件型別
$form->diyForm('field_name')->subComponentType('textarea');

subComponentTypes()

// 與 subComponentType() 作用相同, 圖個方便
$form->diyForm('field_name')->subComponentTypes(['textarea', 'input']);

addComponentType()

// addComponentType() 方法可以新增額外的元件型別
$form->diyForm('name', 'DiyForm')->addComponentType([
    // 元件名稱 (必須包含此項)
    'name'             => '文字域',
    // 元件型別, 可以理解為識別符號, 建議英文 (必須包含此項)
    'type'             => 'textarea',
    // 表單項的label (必須包含此項)
    'label'            => '',
    // 是否必填 1必填 0非必填 (必須包含此項)
    'required'         => 0,
    // 元件的額外屬性
    'props_items'      => [
        // 一個陣列為一項, 都是用input填寫
        [
            // 屬性名稱
            'label' => '顯示行',
            // 對應的元件資料中的key
            'bind'  => 'rows',
        ],
    ],
    // 預設值 (必須包含此項)
    'default_value'    => '',
    // radio/checkbox 等多選元件 的選項資料
    'options'       => [
        // 這個是選項名稱, 一般應該不用改
        'label'  => '選項',
        // 這裡是預設值, [''] 的作用是預設提供一個輸入框
        'values' => [''],
    ],
    // 元件的額外屬性, 用於儲存資料
    'rows'             => 3,
    // js 資料校驗, 如有需要可以給這個鍵放個js的閉包, 需要用如下的方法處理
    'validate_handler' => \Dcat\Admin\Support\JavaScript::make(<<<JS
// 一個js閉包, data與你的自定義項一致, 包括name/type/label....
(data) => {
    // 這裡只能做資料校驗
    if(!data.rows){
        // 返回提示資訊, js會停止往下執行, 並以 Dcat.error() 的方式彈出提示
        return '請輸入顯示行'
    }
    // 資料校驗通過可以不作處理, 或者返個null/false...
}
JS

    ),
]);

addComponentTypes()

// 與 addComponentType() 作用相同, 圖個方便 +1
$form->diyForm('field_name')->subComponentTypes([['自定義元件一的資料'], ['自定義元件二的資料'], ...]);

addPreviewHtml()

// addPreviewHtml() 方法可以新增一段html程式碼到預覽卡片中, 用於自定義元件的顯示
$form->diyForm('field_name')->addPreviewHtml(<<<HTML

<!-- 此處以radio為例, 基本這些類名都需要, 不然樣式不統一 -->
<div class="preview-item" v-if="item.type == 'radio'" :class="'animate-item-' + index">
    <!--表單的label-->
    <label class="d-flex justify-content-between">
        <!--label文字-->
        <div>
            <!-- 如果勾選了必填, 在label前面會有個紅色的 * -->
            <span class="text-danger" v-if="item.required == 1">* </span>
            <!--label 文字-->
            @{{ item.label }}
        </div>
        <!--這裡是操作-->
        <div>
            <!--將當前項往上移-->
            <span class="move-item hover-line"
                  v-if="index != 0"
                  v-on:click="previewItemGoUp(index)">
                <i class="feather icon-arrow-up"></i>
            </span>
            <!--將當前項往下移-->
            <span class="move-item hover-line"
                  v-if="index != contents.length - 1"
                  v-on:click="previewItemGoDown(index)">
                <i class="feather icon-arrow-down"></i>
            </span>
            <!--刪除當前項-->
            <span class="text-danger cursor-pointer hover-line"
                  v-on:click="subPreviewItem(index)">
                移除
            </span>
        </div>
    </label>
    <!--這裡是顯示的表單內容, 就自由發揮吧...-->
    <div class="">
        <div class="custom-control custom-radio custom-control-inline"
             v-for="(opt, opt_key) in item.options.values"
             :key="opt_key">
            <input type="radio"
                   :id="'radio_item_' + index + opt_key"
                   :name="'radio_' + index"
                   :checked="opt == item.default_value"
                   class="custom-control-input">
            <label class="custom-control-label" :for="'radio_item_' + index + opt_key">
                @{{ opt }}
            </label>
        </div>
    </div>
</div>
HTML

);

還有一點

// 在detail()中使用時, 提供了兩個引數
// 第一個是額外的預覽html程式碼, 就是addPreviewHtml()方法傳的那個
// 第二個引數是個bool 預設為true 如果為false 則可以在詳情頁中操作新增的表單 
$show->field('filed_name', 'DiyForm')->diyForm($perview_html, $show_mask);

注意事項

  • 這個元件用的vue.js結合blade
  • 列表顯示沒寫, 有點麻煩 (一般也不會有人把這玩意放列表上吧)
  • 自定義元件型別可能有些不好寫, 不過預設的應該能滿足大部分需求了
  • 有什麼問題可以直接看原始碼, 寫的挺簡單的
  • 儲存的是個json字串, 結構和 addComponentType() 那裡一樣
  • 一般來說 varchar 是存不下的, 對應欄位型別應該使用text或longtext
本作品採用《CC 協議》,轉載必須註明作者和本文連結
海到無涯天作案,山登絕頂我為峰

相關文章