amis 如何让 Table 中的 Switch 列发送请求前弹出确认对话框?

weylhg0b  于 2023-02-04  发布在  其他
关注(0)|答案(5)|浏览(477)
实现场景:

在 Table 或 CURD 中对 Switch 列的开关操作加一层确认对话框

存在的问题:

Switch 组件本身不支持该功能,通过加一个 Button 包装后可以弹出对话框,但是被包裹的 Switch 组件却无法接收到行数据中的值

当前方案:
{
      "name": "boolean",
      "label": "开关",
      "type": "button",
      "actionType": "ajax",
      "confirmText": "确认要更改?",
      "body": {
        "type": "switch",
        "value": "${boolean}" // 无法将 $row.boolean 的值传给 Switch 组件
      },
      "api": "@switch:/amis/api/mock2/sample/${id}:boolean"
}
0sgqnhkj

0sgqnhkj1#

可以参考下 事件动作 ;

由于 Switch 的状态是非受控的,点击上去,他就会进行切换操作,建议取消或失败是 设置成 false,给你一个简单的demo参考一下

{
    "type": "form",
    "id": "form_data",
    "data": {
        "title": "操作确认",
        "msg": "要删除它吗?"
    },
    "body": [
        {
            "type": "switch",
            "label": "确认对话框(模态)",
            "name": "switch",
            "level": "primary",
            "onEvent": {
                "change": {
                    "actions": [
                        {
                            "actionType": "dialog",
                            "args": {
                                "dialog": {
                                    "type": "dialog",
                                    "title": "模态弹窗",
                                    "body": "确定切换?",
                                    "onEvent": {
                                        "confirm": {
                                            "actions": [
                                                {
                                                    "actionType": "setValue",
                                                    "componentId": "form_data",
                                                    "args": {
                                                        "value": {
                                                            "switch": true
                                                        }
                                                    }
                                                }
                                            ]
                                        },
                                        "cancel": {
                                            "actions": [
                                                {
                                                    "actionType": "setValue",
                                                    "componentId": "form_data",
                                                    "args": {
                                                        "value": {
                                                            "switch": false
                                                        }
                                                    }
                                                }
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    ]
                }
            }
        }
    ]
}
pdtvr36n

pdtvr36n2#

@meerkat-morecats
取消或失败时不是设置成false,而是退回到原状态,问题是我怎么在 setValue 时拿到当前行中的 switch 的值?

vxbzzdmp

vxbzzdmp3#

@meerkat-morecats 取消或失败时不是设置成false,而是退回到原状态,问题是我怎么在 setValue 时拿到当前行中的 switch 的值?

直接在column里配置 switch组件呢

fcwjkofz

fcwjkofz4#

直接在column里配置 switch组件呢

直接配置 switch 组件则没有办法配置 action 和 confirmText

我现在能想到的方案是封装一个 ActionSwitch 组件来实现

70gysomp

70gysomp5#

可以通过修改SwitchControl、Switch源代码实现需求(因为我是使用sdk方式,在vue3中使用,还没有研究如何自己封装新的组件,就先直接修改源代码了)。自己写组件估计思路也是大差不差的。大概思路是:通过配置column,增加一个ignorecheck属性和一个自定义的ignorecheck事件。通过这两个属性达到需要的效果:点击switch时不切换值,且不触发change事件,而是通过ignorecheck事件自己进行后续的逻辑处理,点击confirm后再设置crud组件的data值。
其中用到了一些未公开的方法,例如action事件的第三个参数涉及的context、parent、store.reInitData等,这些逻辑是通过分析CRUD组件的handleQuery方法得到的,估计不会大改,改了也没关系,不用太在意。
具体步骤(使用的amis版本为2.6.0,我是使用sdk方式在vue3中使用,需要一些特殊方法,将源代码补丁到sdk.js中):
1)schema配置:

{
            "name": "boolean",
            "label": "开关",
            "type": "switch",
            ignorecheck:true,
            onEvent: {
              ignorecheck: {
                actions: [
                {
                    actionType: 'dialog',
                    dialog:{
                      title: '确认要更改?',
                      onEvent: {
                        confirm: {
                          actions: [
                            {
                              "actionType": "custom",
                              script:"let crud, parent = arguments[2].context.scoped, loop = 0;\
                                  while(parent && !crud && loop++ < 10) {\
                                    crud = parent.getComponents().find(ele => ele.props.type == 'crud');\
                                    parent = parent.parent;\
                                  }\
                                  let item = crud.props.data.items.find(ele => ele.id = arguments[2].data.id);\
                                  item.boolean = !item.boolean;\
                                  crud.props.store.reInitData(crud.props.store.data, false);",
                            },
                          ]
                        },
                      }
                    }
                  },
                ],
              },
            }
          }

2)修改Switch的onClick事件处理代码,如下:

Switch.prototype.hanldeCheck = function (e) {
            var _a = this.props, trueValue = _a.trueValue, falseValue = _a.falseValue, onChange = _a.onChange;
            if (_a.ignorecheck) {
                e.stopPropagation();
                if (onChange) {
                    onChange('ignorecheck');
                    return;
                }
            }
            if (!onChange) {
                return;
            }
            onChange(e.currentTarget.checked ? trueValue : falseValue);
        };

3)需要将schema中的ignorecheck属性传递到react:

SwitchControl.prototype.render = function () {
            var _a = this.props, size = _a.size, className = _a.className; _a.style; var ns = _a.classPrefix, cx = _a.classnames, value = _a.value, trueValue = _a.trueValue, falseValue = _a.falseValue; _a.onChange; var disabled = _a.disabled;
            var _b = this.getResult(), on = _b.on, off = _b.off;
            return (React__default["default"].createElement("div", { className: cx("SwitchControl", className) }, this.renderBody(React__default["default"].createElement(amisUi.Switch, { classPrefix: ns, value: value, trueValue: trueValue, falseValue: falseValue, onText: on, offText: off, disabled: disabled, onChange: this.handleChange, size: size, ignorecheck:_a.ignorecheck }))));
        };

4)再修改SwitchController的onChange事件处理代码:

SwitchControl.prototype.handleChange = function (checked) {
            return tslib.__awaiter(this, void 0, void 0, function () {
                var _a, dispatchEvent, onChange, rendererEvent;
                return tslib.__generator(this, function (_b) {
                    switch (_b.label) {
                        case 0:
                            _a = this.props, dispatchEvent = _a.dispatchEvent, onChange = _a.onChange;
                            if (checked === 'ignorecheck') {
                                return [4 /*yield*/, dispatchEvent('ignorecheck', amisCore.resolveEventData(this.props, { value: _a.data }, 'value'))];    
                            }
                            return [4 /*yield*/, dispatchEvent('change', amisCore.resolveEventData(this.props, { value: checked }, 'value'))];
                        case 1:
                            if (checked === 'ignorecheck') {
                                return [2 /*return*/];
                            }
                            rendererEvent = _b.sent();
                            if (rendererEvent === null || rendererEvent === void 0 ? void 0 : rendererEvent.prevented) {
                                return [2 /*return*/];
                            }
                            onChange && onChange(checked);
                            return [2 /*return*/];
                    }
                });
            });
        };

相关问题