AlpacaJS:动态 table 行中的可观察引用字段
AlpacaJS: Observable referencing fields in a dynamic table row
我有一个 table 元素,人们可以在其中添加行以添加数据。其中两个字段是相互排斥的:如果您在一个字段中输入一个值,则应禁用另一个字段,反之亦然。我的理解是我需要在 postRender
回调中使用可观察对象执行此操作,但我似乎无法找到正确的路径或 ID 字符串。从逻辑上讲,它的工作方式没有多大意义。 table 一开始是空的。
那么是否有 "Add Row" 按钮的回调或我需要添加此逻辑的地方?任何指导将不胜感激。
架构:
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
总是有帮助,但在这种情况下不会太多,因为你喜欢嵌套 fields/objects ( array > items > item 1 > hours ) 这就是为什么您的代码不起作用的原因,因为您无法将更改功能分配给所有已创建项目的所有时间!另外,您在数字上使用 getValue().length
(请参阅您的架构配置),这将永远行不通,您应该在 number
字段上使用 toString
或 isNaN
。
因此,要实现您正在寻找的内容,您应该创建一个 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。
并回答你关于 "Add Row" 按钮的问题,是的,有一个回调,但我认为它不会帮助你,虽然我试过了,你有数组类型字段2 个不同的添加按钮,所以对我来说这不是一个好的解决方案,因为您应该为两个按钮实现代码!第一个是当你有 0 个项目时(工具栏按钮),第二个是当你开始添加项目时(操作按钮)。
我有一个 table 元素,人们可以在其中添加行以添加数据。其中两个字段是相互排斥的:如果您在一个字段中输入一个值,则应禁用另一个字段,反之亦然。我的理解是我需要在 postRender
回调中使用可观察对象执行此操作,但我似乎无法找到正确的路径或 ID 字符串。从逻辑上讲,它的工作方式没有多大意义。 table 一开始是空的。
那么是否有 "Add Row" 按钮的回调或我需要添加此逻辑的地方?任何指导将不胜感激。
架构:
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
总是有帮助,但在这种情况下不会太多,因为你喜欢嵌套 fields/objects ( array > items > item 1 > hours ) 这就是为什么您的代码不起作用的原因,因为您无法将更改功能分配给所有已创建项目的所有时间!另外,您在数字上使用 getValue().length
(请参阅您的架构配置),这将永远行不通,您应该在 number
字段上使用 toString
或 isNaN
。
因此,要实现您正在寻找的内容,您应该创建一个 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。
并回答你关于 "Add Row" 按钮的问题,是的,有一个回调,但我认为它不会帮助你,虽然我试过了,你有数组类型字段2 个不同的添加按钮,所以对我来说这不是一个好的解决方案,因为您应该为两个按钮实现代码!第一个是当你有 0 个项目时(工具栏按钮),第二个是当你开始添加项目时(操作按钮)。