Fastadmin中的键值组件(Fieldlist)

Php   2025-11-07 13:40   67   0  

键值组件是FastAdmin开发的一项简洁实用的基础组件,在FastAdmin中很多模块都有使用到该组件,例如常规管理->系统配置->字典配置均使用此组件开发。

组件特点

1、支持一维数组和二维数组数据源
2、支持添加、删除、排序
3、支持自定义列表模板

数据源

fieldlist组件支持一维数组和二维数组数据源,默认为一维数组数据源,如果需要使用二维数组数据源,请务必同时使用自定义模板功能才支持。

一维数组数据源示例:

<textarea name="row[configgroup]" class="form-control hide" cols="30" rows="5">
    {
        "basic":"基础配置",
        "email":"邮件配置",
        "dictionary":"字典配置",
        "user":"会员配置",
        "example":"示例分组"
    }
</textarea>


二维数组数据源示例:

<textarea name="row[test]" class="form-control hide" cols="30" rows="5">
    [
        {"name":"张三","gender":"男","age":"23","score":"80"},
        {"name":"李四","gender":"男","age":"26","score":"90"}
    ]
</textarea>


常规示例

以下是键值组件常用的一维数组数据源使用方法:

<dl class="fieldlist" data-name="row[configgroup]">
    <dd>
        <ins>键名</ins>
        <ins>键值</ins>
    </dd>
    <dd>
        <a href="javascript:;" class="btn btn-sm btn-success btn-append"><i class="fa fa-plus"></i> 追加</a>
    </dd>
    <textarea name="row[configgroup]" class="form-control hide" cols="30" rows="5">{"basic":"基础配置","email":"邮件配置","dictionary":"字典配置","user":"会员配置","example":"示例分组"}</textarea>
</dl>


通过将以上代码放置在我们的表单中,然后使用Form.api.bindevent("form")或Form.events.fieldlist("form")进行初始化即可。

自定义模板

以上是最简洁的使用方法,fieldlist还有更强大的自定义功能来实现自定义模板和二维数组数据源,如下:

<dl class="fieldlist" data-name="row[test]" data-template="testtpl">
    <dd>
        <ins>姓名</ins>
        <ins>性别</ins>
        <ins>年龄</ins>
        <ins>成绩</ins>
    </dd>
    <dd>
        <a href="javascript:;" class="btn btn-sm btn-success btn-append"><i class="fa fa-plus"></i> 追加</a>
    </dd>
    <textarea name="row[test]" class="form-control hide" cols="30" rows="5">[{"name":"张三","gender":"男","age":"23","score":"80"},{"name":"李四","gender":"男","age":"26","score":"90"}]</textarea>
</dl>
<!--定义模板,模板语法使用Art-Template模板语法-->
<script type="text/html" id="testtpl">
    <dd class="form-inline">
        <input type="text" name="<%=name%>[<%=index%>][name]" class="form-control" value="<%=row['name']%>" size="10"> 
        <input type="text" name="<%=name%>[<%=index%>][gender]" class="form-control" value="<%=row['gender']%>" size="30"> 
        <input type="text" name="<%=name%>[<%=index%>][age]" class="form-control" value="<%=row['age']%>" size="30"> 
        <input type="text" name="<%=name%>[<%=index%>][score]" class="form-control" value="<%=row['score']%>" size="30"> 
        <span class="btn btn-sm btn-danger btn-remove"><i class="fa fa-times"></i></span> <span class="btn btn-sm btn-primary btn-dragsort"><i class="fa fa-arrows"></i></span>
    </dd>
</script>

在自定义模板中有固定的变量,如<%=name%><%=index%><%=row['列名']%>,说明如下:

变量说明示例结果
name字段名称,该值将会替换为data-name中的值<%=name%>row[test]
index渲染行的索引值,该值会递增,但并不保证连续<%=index%>0
row数组行的数据<%=row['gender']%>
key键名的值,该值仅用于键值数组时使用<%=key%>test
value键值的值,该值仅用于键值数组时使用<%=value%>value

温馨提示:使用自定义模板时,二维数据请勿仅使用key和value这个键名,会导致被识别为键值数组。


表格布局

fieldlist默认使用的是dl dd布局,此外还支持使用table来进行布局,达到更好的展示效果,如下:

<table class="table table-responsive fieldlist" data-name="row[test]" data-template="testtpl" data-tag="tr">
    <tr>
        <td>姓名</td>
        <td>性别</td>
        <td>年龄</td>
        <td>成绩</td>
        <td></td>
    </tr>
    <tr>
        <td colspan="5"><a href="javascript:;" class="btn btn-sm btn-success btn-append"><i class="fa fa-plus"></i> 追加</a></td>
    </tr>
    <textarea name="row[test]" class="form-control hide" cols="30" rows="5">[{"name":"张三","gender":"男","age":"23","score":"80"},{"name":"李四","gender":"男","age":"26","score":"90"}]</textarea>
</table>
<!--定义模板,模板语法使用Art-Template模板语法-->
<script type="text/html" id="testtpl">
    <tr class="form-inline">
        <td><input type="text" name="<%=name%>[<%=index%>][name]" class="form-control" value="<%=row['name']%>" size="10"></td> 
        <td><input type="text" name="<%=name%>[<%=index%>][gender]" class="form-control" value="<%=row['gender']%>" size="30"></td> 
        <td><input type="text" name="<%=name%>[<%=index%>][age]" class="form-control" value="<%=row['age']%>" size="30"></td> 
        <td><input type="text" name="<%=name%>[<%=index%>][score]" class="form-control" value="<%=row['score']%>" size="30"></td>
        <td><span class="btn btn-sm btn-danger btn-remove"><i class="fa fa-times"></i></span> <span class="btn btn-sm btn-primary btn-dragsort"><i class="fa fa-arrows"></i></span></td>
    </tr>
</script>


可以看到我们我们给table添加了一个额外的属性data-tag="tr"
通过以上定义,可以任意自定义我们展示项的数据。
使用表格布局时必须使用自定义模板,且自定义模板中的第一个DOM元素必须是<tr>

事件绑定

如果我们需要在点击追加按钮以后再对新增的展示项绑定事件,我们可以在JS中通过监听事件来给新增的元素绑定事件,这种情况常用于我们自定义列表中有表单组件,如日期选择、上传按钮、动态下拉等情况下使用。

$(document).on("fa.event.appendfieldlist", '[data-name="row[test]"] .btn-append', function(e, obj){
    //通用的表单组件事件绑定和组件渲染
      Form.api.bindevent($(obj));
});

如果我们在JS中外部对fieldlist中的组件做了修改,此时我们需要手动触发下组件的change事件,如:

$("[data-name='row[test]'] input:first-child").trigger("change");

通过以上代码来触发input的change事件,此时我们隐藏的textarea值才会刷新,否则textarea仍然是旧的数据

重新渲染

如果我们通过JS手动修改了隐藏的textarea的值,此时需要重新渲染我们的fieldlist组件,我们可以通过

$("[data-name='row[test]'] textarea[name='test']").trigger("fa.event.refreshfieldlist");

来重新渲染我们的组件

追加数据

如果我们希望在外部追加数据,可以通用调用追加按钮的点击事件并透传数据来实现

var data ={
    "name":"王五",
    "gender":"男",
    "age":"22",
    "score":"60"
};
$("[data-name='row[test]'] .btn-append").trigger("click", [data]);


整合上传组件

html部分:

<style>
    .upload-image {
        background: url('/assets/img/plus.png') no-repeat center center;
        background-size: 30px 30px;
        height: 30px;
        width: 30px;
        border: 1px solid #ccc;
    }
</style>
<dl class="fieldlist" data-template="leveltpl" data-name="row[{name}]" id="second-table">
    <dd>
        <ins>标题名称</ins>
        <ins>描述文字</ins>
        <ins>icon地址</ins>
        <ins>按钮文字</ins>
        <ins>跳转地址</ins>
    </dd>
    <dd><a href="javascript:;" class="btn btn-sm btn-success btn-append"><i class="fa fa-plus"></i> 追加</a></dd>
    <textarea name="row[{name}]" class="form-control hide" cols="30" rows="5">{value}</textarea>
</dl>
<script id="leveltpl" type="text/html">
    <dd class="form-inline">
        <ins>
            <input type="text" name="row[<%=name%>][<%=index%>][name]" class="form-control" value="<%=row['name']%>" placeholder="标题名称" size="10">
        </ins>

        <ins>
            <input type="text" name="row[<%=name%>][<%=index%>][text]" class="form-control" value="<%=row['text']%>" placeholder="描述文字" size="10">
        </ins>
        <ins>
            <input type="hidden" name="<%=name%>[<%=index%>][image]" id="c-image-<%=index%>" value="<%=row.image%>">
            <button type="button" id="faupload-image" class="btn btn-danger faupload upload-image" data-input-id="c-image-<%=index%>" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp,image/webp" data-multiple="false" <%if(row.image){%>style="background-image: url('<%=row.image%>')"<%}%>></button>
        </ins>
        <ins>
            <input type="text" name="row[<%=name%>][<%=index%>][gowhat]" class="form-control" value="<%=row['gowhat']%>" placeholder="按钮文字" size="10">
        </ins>
        <ins>
            <input type="text" name="row[<%=name%>][<%=index%>][pages]" class="form-control" value="<%=row['pages']%>" placeholder="跳转地址" size="10">
        </ins>

        <span class="btn btn-sm btn-danger btn-remove"><i class="fa fa-times"></i></span>
        <span class="btn btn-sm btn-primary btn-dragsort"><i class="fa fa-arrows"></i></span>
    </dd>
</script>


js部分:

index: function () {

    // 自定义上传图片
    $(document).on("fa.event.appendfieldlist", "#second-table .btn-append", function (e, obj) {
        //绑定上传组件
        Form.events.faupload(obj);
        //上传成功回调事件,变更按钮的背景
        $(".upload-image", obj).data("upload-success", function (data) {
            $(this).css("background-image", "url('" + Fast.api.cdnurl(data.url) + "')");
        })
    });
}