MultiDialog 多选对话框

 

MultiDialog 多选对话框同样是继承与Field,仅支持 array 类型的Model属性字段注解。MultiDialog 多选对话框 与 SelectDialog 单选对话框 不同在于,多选对话框可以选择多个选项数据.

 

除了Field 的属性支持以外,MultiDialog 多选对话框自己的属性设置选项如下:


public string $url = '';

打开的对话框URL地址,支持虚拟URL地址。

 

public int $mode = 1;

填充值的模式,1 是完整填充,包括值与文本,2 是仅填充值
如:

#mode =2 时填充的值为
[1,3,4]
#mode =1 是填充的值为

[{"value"=>1,"text":"选项1"},{"value"=>3,"text":"选项3"},{"value"=>4,"text":"选项4"}]



public string $textSql = '';

使用值获取对应文本的SQL语句, 仅适用于 mode=2 的情况。

例如:

textSql:'select name from @pf_category where id=?'

 

public string|array|null $textFunc = null;

指定值获取对应文本的函数指定,仅适用于 mode=2 的情况。

函数定义为:

function($value):string

如:

     #[MultiDialog(
        label: '选择文章1',
        url: '~/multi_dialog',
        textFunc: [self::class, 'getSelectName']
    )]
    public array $select = [];

    public static function getSelectName(int|string $value): string
    {
        $row = DB::getRow('select title from @pf_article where id=?', $value);
        if ($row == null) {
            return '';
        }
        return $row['title'];
    }

 

public string $itemType = 'string';

在 mode=2 时,每项数据的填充类型。 如果期望是 int  则填写int。

为了演示效果,我们先制作一个用于选择的对话框页面:
控制器代码如下:

/app/home/controller/MultiDialog.php

<?php


namespace app\home\controller;


use beacon\core\Controller;
use beacon\core\DBSelector;
use beacon\core\Method;

class MultiDialog extends Controller
{
    //用于提供穿梭框的数据的
    #[Method(act: 'index', method: Method::POST | Method::GET)]
    public function index(string $keyword = '')
    {
        #非ajax请求直接返回页面。
        if (!$this->isAjax()) {
            $this->display('multi_dialog.tpl');
            return;
        }

        $selector = new DBSelector('@pf_article');
        $selector->search("title like concat('%',?,'%')", $keyword);
        $data = $selector->pageData();
        #定义一个字符串模板,用于修饰 $data['list'] 数据。
        $template = <<<'TPL'
        {hook fn='_choice' rs}<input type="checkbox" class="check-item" data-value="{$rs.id}" data-text="{$rs.title}" value="{$rs.id}"/>{/hook}
        {hook fn='columnName' rs}{$rs.columnId|column}{/hook}
        {hook fn='categoryName' rs}{$rs.categoryId|category}{/hook}
        TPL;
        # 以上模板用到 修饰器 column 和 category 是自定义的模板修饰器,可参考 sdopx.wj008.net 模板引擎 修饰器的制作。
        # column 是columnId 兑换 栏目名称的修饰器
        # category 是categoryId 兑换 栏目名称的修饰器

        $data['list'] = $this->hookData($data['list'], 'string:' . $template, 'rs', true);
        $this->success('ok', $data);
    }
}

对应的模板文件如下:

<!doctype html>
<html lang="zh-cn">
<head>
    <meta charset="utf-8">
    <title>多选对话框</title>
    <link type="text/css" rel="stylesheet" href="/yeeui/css/yeeui.css"/>
    <link type="text/css" rel="stylesheet" href="/icofont/icofont.css"/>
    <script src="/yeeui/third/jquery-3.3.1.min.js"></script>
    <script src="/yeeui/third/vue.min.js"></script>
    <script src="/yeeui/yee.js"></script>
    {literal}
        <style>
            html, body {
                background: #fff;
            }
        </style>
    {/literal}
</head>
<body>
<div class="yee-wrap yee-dialog">

    <div class="yee-tab">
        <!--YeeUI 标签切换控件-->
        <ul style="float:left;" yee-module="form-tab">
            <li class="curr" data-bind-name="main-list"><a href="javascript:;">待选</a></li>
            <li data-bind-name="selected-list"><a href="javascript:;">已选</a></li>
        </ul>
        <div class="yee-tab-right">
            <span> 已选 <span id="selected-count" class="green">0</span>/<span id="records-count">0</span> 条记录</span>
        </div>
    </div>

    <div name="main-list">

        <div class="yee-list-search">
            <!--YeeUI ajax搜索表单控件-->
            <form id="searchForm" yee-module="search-form" data-bind="#list">
                <div class="yee-cell">
                    <label class="yee-label">文章标题:</label>
                    <span><input name="keyword" class="form-inp text" type="text"/></span>
                </div>
                <div class="yee-cell">
                    <input class="form-btn blue" value="查询" type="submit"/>
                    <input class="form-btn normal" value="重置" type="reset"/>
                    <input type="hidden" name="sort">
                </div>
            </form>
        </div>

        <div class="scrollbar" style="height:calc(100vh - 200px);overflow-y: auto">
            <!--YeeUI 数据显示控件-->
            <table id="list" width=100% class="yee-datatable" yee-module="datatable" data-auto-load="true">
                <thead>
                <tr>
                    <th width="40"><input type="checkbox"></th>
                    <th align="center" width="60">id</th>
                    <th align="left">文章标题</th>
                    <th align="center" width="80">栏目类别</th>
                    <th align="center" width="80">文章分类</th>
                    <th align="center" width="80">点击数</th>
                    <th align="center" width="180">创建时间</th>
                </tr>
                </thead>
                <tbody yee-template="vue">
                <tr v-for="rs in list">
                    <td align="center" v-html="rs._choice"></td>
                    <td align="center" v-html="rs.id"></td>
                    <td align="left" v-html="rs.title"></td>
                    <td align="center" v-html="rs.columnName"></td>
                    <td align="center" v-html="rs.categoryName"></td>
                    <td align="center" v-html="rs.hits"></td>
                    <td align="center" v-html="rs.addTime"></td>
                </tr>
                <tr v-if="list.length==0">
                    <td colspan="100"> 没有任何数据信息....</td>
                </tr>
                </tbody>
            </table>
        </div>
        <!--YeeUI 分页控件-->
        <div yee-module="pagebar" data-bind="#list" class="yee-pagebar">
            <div yee-template="vue">
                <div class="pagebar" v-html="barCode"></div>
                <div class="pagebar-info">共有信息:<span v-text="recordsCount"></span> 页次:<span v-text="page"></span>/<span v-text="pageCount"></span> 每页<span v-text="pageSize"></span></div>
            </div>
        </div>
    </div>
    <!--用于显示已选中数据-->
    <div name="selected-list" class="scrollbar" style="height:calc(100vh - 100px);overflow-y: auto">
        <table id="selected-table" class="yee-datatable" border="0" width="100%" style="background:#fff;">
            <thead>
            <tr>
                <th align="center" width="60">ID值</th>
                <th align="left">已选选项(文本)</th>
                <th width="80">操作</th>
            </tr>
            </thead>
            <tbody>
            <tr v-for="rs in Object.values(select)">
                <td align="center" v-text="rs.value"></td>
                <td align="left" v-text="rs.text"></td>
                <td align="center"><a href="javascript:;" class="yee-btn remove" style="margin-right: 5px" @click="remove(rs)">移除</a></td>
            </tr>
            </tbody>
        </table>
    </div>

    <div class="yee-submit" style="position: fixed; right: 0; bottom: 0; margin: 0px; padding: 10px 0; text-align: right;">
        <input id="select-btn" type="button" class="form-btn red" style="margin-right: 10px;" value="确定"/>
        <a id="close-btn" href="javascript:;" style="margin-right: 20px;" class="form-btn">关闭</a>
    </div>
</div>

{literal}
    <script>
        //当对话框初始化完成后,该函数会返回 dialog 的对话框句柄。
        Yee.readyDialog(function (dialog) {
            let dataMap = {};
            let table = $("#list");

            //使用vue渲已选中的数据
            let app = new Vue({
                el: '#selected-table',
                data: {
                    select: []
                },
                methods: {
                    remove: function (value) {
                        removeItem(value);
                        refreshItem();
                    }
                }
            });

            function addItem(item) {
                let key = item.value;
                //去重,如果已经存在,不要再加入
                if (dataMap[key] !== void 0) {
                    return;
                }
                dataMap[key] = item;
                app.select.push(item);
                $("#selected-count").text(app.select.length);
            }

            function removeItem(item) {
                let key = item.value;
                delete dataMap[key];
                let temp = [];
                for (let i = 0; i < app.select.length; i++) {
                    let k = app.select[i].value;
                    if (dataMap[k]) {
                        temp.push(app.select[i]);
                    }
                }
                app.select = temp;
                $("#selected-count").text(app.select.length);
            }

            //刷新列表中的 勾选状态
            function refreshItem() {
                table.find(':checkbox').prop('checked', false);
                for (let key in dataMap) {
                    let rs = dataMap[key] || null;
                    if (rs) {
                        table.find(':checkbox.check-item[value=' + rs.value + ']').prop('checked', true);
                    }
                }
            }

            function setBox(elem) {
                let box = $(elem);
                let data = box.data() || {};
                if (!box.prop('checked')) {
                    removeItem(data);
                } else {
                    addItem(data);
                }
            }

            //关闭对话框
            $('#close-btn').on('click', function () {
                dialog.close();
            });

            //确定选择
            $('#select-btn').on('click', function () {
                let items = [];
                for (let i = 0; i < app.select.length; i++) {
                    let rs = app.select[i];
                    if (rs) {
                        items.push(rs);
                    }
                }
                //使用对话框句柄返回数据 items 数据
                dialog.success(items);
                //关闭对话框
                dialog.close();
            });

            //列表控件更新后
            table.on("render", function (ev, source) {
                $("#records-count").text(source.pageInfo.recordsCount || "0");
                refreshItem();
            });

            table.on('click', 'input:checkbox', function () {
                if ($(this).is('.check-item')) {
                    setBox(this);
                } else {
                    setTimeout(function () {
                        $('#list').find('input:checkbox.check-item').each(function (_, elem) {
                            setBox(elem);
                        });
                    }, 1);
                }
            });

            //从对话框中拿取传过来的数据
            if (dialog !== void 0 && dialog.assign && Yee.isArray(dialog.assign)) {
                let items = dialog.assign || [];
                for (let i = 0; i < items.length; i++) {
                    if (items[i].value !== void 0) {
                        addItem(items[i]);
                    }
                }
            }
        });
    </script>
{/literal}

</html>



现在我们修改主Model 来设置多选对话框的使用

UserModel


namespace app\home\model;

use beacon\core\DB;
use beacon\core\Form;
use beacon\widget\MultiDialog;
use beacon\widget\Text;
use beacon\widget\Textarea;

#注意 这里需要使用表单注解
#[Form(title: '用户表单', table: '@pf_user', template: 'user.form.tpl')]
class UserModel
{

    #[Text(
        label: '团队名称',
        validRule: ['r' => '请填写团队名称'],
    )]
    public string $groupName = '';


    #[MultiDialog(
        label: '选择文章1',
        url: '~/multi_dialog',
        mode: 2,
        itemType:'int',
        textFunc: [self::class, 'getSelectName'],
        attrs: [
            'data-width' => 1000,#指定对话框宽
            'data-height' => 600,#指定对话框高
            'data-btn-text' => '选择文章', #指定按钮文本
        ]
    )]
    public array $select1 = [];


    #[MultiDialog(
        label: '选择文章2',
        url: '~/multi_dialog',
    )]
    public array $select2 = [];


    #[Textarea(
        label: '团队介绍',
        validRule: ['r' => '请填写个人介绍'],
    )]
    public string $intro = '';

    public static function getSelectName(int|string $value): string
    {
        $row = DB::getRow('select title from @pf_article where id=?', $value);
        if ($row == null) {
            return '';
        }
        return $row['title'];
    }
}


模板文件:

<!doctype html>
<html lang="zh-cn">
<head>
    <meta charset="utf-8">
    <title>{$form->title}</title>
    <link type="text/css" rel="stylesheet" href="/yeeui/css/yeeui.css"/>
    <link type="text/css" rel="stylesheet" href="/icofont/icofont.css"/>
    <script src="/yeeui/third/jquery-3.3.1.min.js"></script>
    <script src="/yeeui/yee.js"></script>
</head>
<body>
<div style="margin: 20px">
    <form method="post" yee-module="ajax validate">
        <div class="yee-panel">
            <div class="panel-caption">
                {if $form->getType()=='add'}添加{elseif $form->getType()=='edit'}编辑{/if}{$form->title}
            </div>
            <div class="panel-content">
                {foreach from=$form->getViewFields() item=field}
                    {field_row field=$field}
                {/foreach}
            </div>
            <div class="yee-submit">
                <label class="submit-label"></label>
                <div class="submit-cell">
                    {*输出隐藏域*}
                    {$form->fetchHideBox()|raw}
                    <input type="submit" class="form-btn red" value="提交">
                </div>
            </div>
        </div>
    </form>
</div>
</html>


控制器文件:

namespace app\home\controller;


use app\home\model\UserModel;
use beacon\core\Controller;
use beacon\core\Form;
use beacon\core\Logger;
use beacon\core\Method;

class User extends Controller
{
    #[Method(act: 'index', method: Method::GET)]
    public function index()
    {
        $form = Form::create(UserModel::class, 'add');
        $this->displayForm($form);
    }

    #[Method(act: 'index', method: Method::POST)]
    public function add()
    {
        $user = new UserModel();
        $form = Form::create($user, 'add');
        $input = $this->completeForm($form);
        Logger::log($input); #input 可以用用于插入或者更新数据库。
        Logger::log($user);
        //这里需要有返回值 否则 ajax 提交会没有任何内容返回
        $this->success('ok');
    }

}


最终效果如下:


对话框已选效果:


填完表单,提交后的 debug.php 页面输出如下:

{
    "groupName": "测试团队",
    "select1": [
        5,
        7
    ],
    "select2": [
        {
            "text": "Manjaro",
            "value": 9
        },
        {
            "text": "Deepin15.7 编译安装 php 7.2",
            "value": 10
        },
        {
            "text": "今天聊聊 Elasticsearch 在PHP项目中的使用。",
            "value": 7
        }
    ],
    "intro": "这个也帅。"
}

{
    "___class_name": "app\\home\\model\\UserModel",
    "groupName": "测试团队",
    "select1": [
        5,
        7
    ],
    "select2": [
        {
            "text": "Manjaro",
            "value": 9
        },
        {
            "text": "Deepin15.7 编译安装 php 7.2",
            "value": 10
        },
        {
            "text": "今天聊聊 Elasticsearch 在PHP项目中的使用。",
            "value": 7
        }
    ],
    "intro": "这个也帅。"
}



上一篇:SelectDialog 单选对话框
下一篇:YeeUI 介绍
Copyright © 2021 海南的叶子 All Rights Reserved 琼ICP备2021000725号

琼公网安备 46900702000037号