【问题标题】:AlpacaJS: Observable referencing fields in a dynamic table rowAlpacaJS:动态表行中的可观察引用字段
【发布时间】:2020-08-21 23:09:43
【问题描述】:

我有一个表格元素,人们可以在其中添加行以添加数据。其中两个字段是互斥的:如果您在一个字段中输入值,则应禁用另一个字段,反之亦然。我的理解是我需要在 postRender 回调中使用 observables 执行此操作,但我似乎无法找到正确的路径或 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 的方法;它一直显示为 @987654327 @)。所以我选择了以下解决方案,这就足够了。这是options对象的相关sn-p:

            "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)),但现在它的功能已经足够了。

【问题讨论】:

    标签: javascript alpacajs


    【解决方案1】:

    您的架构是正确的,并且您的想法也是正确的这就是为什么您的代码不起作用的原因,因为您无法将更改功能分配给所有已创建项目的所有时间!另外,您在数字上使用了getValue().length(请参阅您的架构配置),这将永远无法使用,您应该在number 字段上使用toStringisNaN

    因此,要实现您正在寻找的内容,您应该创建一个 options config 并将其分配给 alpaca 选项字段。在这个配置中,您应该在百分比和小时字段上使用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() 函数来告诉 alpaca 您更新了一些配置并使用更新后的配置为我们重新呈现该字段。

    percent.refresh();
    

    这是此解决方案的有效fiddle

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

    【讨论】:

    • 非常感谢您,Vert3x!我只是没想过在活动中尝试this.parent。启示录!感谢您的帮助。
    • 现在唯一的问题是,当我添加新行时,它会记住上一行的禁用/启用设置。现在来追踪它:) 我认为它与桌子上的add 事件有关。
    • 哦!好的,我明白了,对于您的情况,还有另外两种复杂的解决方案,您应该创建自定义模板并处理车把……我不喜欢,或者您创建自定义字段,对我来说,后者比处理更容易handelbars,我会做一些测试并给你另一个解决方案,可以吗?
    • 在您更新 postRenderCallback 之后,您是否尝试过不仅使用最后渲染的操作栏来添加项目?您是否尝试过再次使用第一个操作栏添加项目?我认为您的 postRenderCallback 代码在某些情况下将不起作用。
    • 对于项目验证,有一种更简洁的方法,您能否为此发布另一个问题,因为它与这个问题无关?对于禁用这些字段,我有一个解决方案,如果您需要其他解决方案,请告诉我,我会为您发布。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-23
    • 1970-01-01
    • 2022-01-21
    • 1970-01-01
    • 2014-07-22
    相关资源
    最近更新 更多