我有一个表格元素,人们可以在其中添加行以添加数据。其中两个字段是互斥的:如果您在一个字段中输入一个值,则应禁用另一个字段,反之亦然。我的理解是,我需要使用可观察对象在postRender回调中执行此操作,但是我似乎找不到正确的路径或ID字符串。从逻辑上讲,它如何工作没有多大意义。该表开始为空。

因此,是否存在“添加行”按钮的回调或需要添加此逻辑的内容?任何指导将不胜感激。

架构:

    var schema = {
        "type": "object",
        "properties": {
            "cbnum": {
                "type": "string",
                "required": true,
                "minLength": 5,
                "maxLength": 5
            },
            "projects": {
                "type": "array",
                "items": {
                    "type": "object",
                    "properties": {
                        "name": {
                            "type": "string",
                            "title": "Project name (required)",
                            "required": true
                        },
                        "tags": {
                            "type": "string",
                            "title": "Tags"
                        },
                        "hours": {
                            "type": "number",
                            "title": "Hours"
                        },
                        "percent": {
                            "type": "number",
                            "title": "Percent"
                        }
                    }
                }
            }
        }
    };


以下代码不起作用(再次考虑时,这并不奇怪,但我不知道该尝试什么):

    var postRenderCallback = function(control) {
        var hours = control.childrenByPropertyId["projects"].childrenByPropertyId["hours"];
        var percent = control.childrenByPropertyId["projects"].childrenByPropertyId["percent"];
        hours.on("change", function() {
            if (this.getValue().length > 0) {
                percent.setValue("");
                percent.options.disabled = true;
            } else {
                percent.options.disabled = false;
            }
        });
        percent.on("change", function() {
            if (this.getValue().length > 0) {
                hours.setValue("");
                hours.options.disabled = true;
            } else {
                hours.options.disabled = false;
            }
        });
    };


更新资料

以下postRenderCallback修复了持久禁用问题:

    var postRenderCallback = function(control) {
        var table = control.childrenByPropertyId["projects"];
        table.on("add", function() {
            var lastrow = this.children[this.children.length-1];
            var hours = lastrow.childrenByPropertyId["hours"];
            var percent = lastrow.childrenByPropertyId["percent"];
            hours.options.disabled = false;
            percent.options.disabled = false;
            hours.refresh();
            percent.refresh();
        });
    };


但是后来我遇到了另外两个问题,这使整个解决方案成为问题(最大的问题是我无法找到一种方法来将数字字段设置为空白或undefined;它一直显示为NaN)。因此,我采用了以下解决方案,就足够了。以下是options对象的相关代码段:

            "projects": {
                "type": "table",
                "actionbarStyle": "bottom",
                "items": {
                    "fields": {
                        "tags": {
                            "type": "tag"
                        },
                        "hours": {
                            "allowOptionalEmpty": true,
                            "validator": function (callback) {
                                var that = this.parent.childrenByPropertyId["percent"];
                                var thisValue = this.getValue();
                                var thatValue = that.getValue();
                                if ( (typeof thisValue !== "undefined" && !isNaN(thisValue)) && (typeof thatValue !== "undefined" && !isNaN(thatValue)) ) {
                                    callback({
                                        "status": false,
                                        "message": "You can only enter a number into one of the fields, if any. You may not have numbers in both."
                                    });
                                } else {
                                    callback({
                                        "status": true
                                    });
                                }
                            }
                        },
                        "percent": {
                            "allowOptionalEmpty": true,
                            "validator": function (callback) {
                                var that = this.parent.childrenByPropertyId["hours"];
                                var thisValue = this.getValue();
                                var thatValue = that.getValue();
                                if ( (typeof thisValue !== "undefined" && !isNaN(thisValue)) && (typeof thatValue !== "undefined" && !isNaN(thatValue)) ) {
                                    callback({
                                        "status": false,
                                        "message": "You can only enter a number into one of the fields, if any. You may not have numbers in both."
                                    });
                                } else {
                                    callback({
                                        "status": true
                                    });
                                }
                            }
                        }
                    }
                }
            }


仍然不是一个完美的UX解决方案(我似乎无法使一个字段的验证器执行另一字段的验证器;我尝试了this.parent.validate(true)),但是到目前为止它的功能已经足够了。

最佳答案

您的模式是正确的,并且使用postRender所考虑的内容也是正确的,但总是有帮助,但在这种情况下,它并不太有用,因为您喜欢嵌套的字段/对象(数组>项目>项目1>小时),这就是为什么代码无法使用,因为您无法将更改功能分配给所有已创建项目的所有时间!加上您在数字上使用getValue().length(请参阅架构配置),这将永远无法工作,您应该使用toString或在isNaN字段上使用number

因此,要实现所需的功能,应创建一个options config并将其分配给羊驼毛选项字段。并且在此配置中,您应在百分比和小时数字段上使用change event,并将与每个字段相同的代码放在postRender上。

这是一个例子:

"hours": {
   "events": {
       "change": function() {
            var percent = this.parent.childrenByPropertyId["percent"];
            var hoursValue = this.getValue();
            if (typeof hoursValue != 'undefined' && !isNaN(hoursValue)) {
              percent.options.disabled = true;
            } else {
              percent.options.disabled = false;
            }
            percent.refresh();
        }
    }
}


postRender中,您已经有一个全局控件变量,可以用来获取字段控件对象,但是这里我们在子控件上,因此可以使用父控件来做到这一点,如下所示:

var percent = this.parent.childrenByPropertyId["percent"];


在为小时或百分比字段设置了任何选项后,应调用refresh()函数,以通知羊驼您更新了一些配置,并使用更新后的配置为我们重新渲染该字段。

percent.refresh();


这是此解决方案的有效fiddle

并回答您有关“添加行”按钮的问题,是的,有一个回调,但是我认为它对数组类型字段没有帮助,但是我尝试使用数组类型字段有2个不同的添加按钮,因此对我来说,这不是一个好的解决方案,因为您应该为两个按钮实现代码!当您有0个项目时,第一个按钮(工具栏按钮);当您开始添加项目时,第二个按钮(操作按钮)。

关于javascript - AlpacaJS:动态表行中的可观察引用字段,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/61644505/

10-12 00:30
查看更多