enaml - 如何根据 Enaml 中另一个字段的值验证一个字段?
问题描述
假设我有一个带有 2 个 IntField 的表单。如何根据 IntField A 中的输入验证 IntField B?例如,如果 A == 1,则 B 只能在 0-30 之间;如果A == 2,B只能在0-50之间;else B 可以是任何其他数字
从我所能谷歌的所有内容中,我只能找到 IntValidator 仅验证该字段而无法链接到另一个字段。我找不到任何示例来显示如何更新 IntValidator 中的最小/最大值,也没有任何自定义验证器可以获取另一个字段的值,以便验证可以根据另一个字段中值的变化而改变......
enamldef IntFieldsWindow( Window ):
Container:
Form:
padding=0
Label:
text = 'Field A'
IntField: fld_a:
value = 0
Label:
text = 'Field B'
IntField: fld_b:
value = 0
经过一番测试,其实是可以将fld_a传递给自定义验证器,然后在validate函数中获取fld_a.value,最后将自定义验证器设置为fld_b。不确定这是否是进行此类验证的方法。
解决方案
一种方法是将数据分解成一个模型,并让它使用一个观察者来验证成员,当任何一个成员发生变化时都会调用该观察者。
然后IntField
绑定到模型值(使用<<
)并使用通知处理程序(::
)更新模型值,该处理程序捕获并报告验证错误。
例如:
from atom.api import Atom, Int, observe
from enaml.stdlib.fields import IntField
from enaml.widgets.api import Window, Container, Label, Form
class Model(Atom):
a = Int()
b = Int()
@observe('a', 'b')
def _validate(self, change):
# When a or b is changed validate the model state
a, b = self.a, self.b
if a == 1:
if b < 0 or b > 30:
raise ValueError("B is out of range")
elif a == 2:
if b < 0 or b > 50:
raise ValueError("B is out of range")
enamldef Main(Window):
attr model = Model()
Container:
Form:
padding=0
Label:
text = 'Field A'
IntField: fld_a:
value << model.a
value ::
error.text = ''
try:
model.a = change['value']
except ValueError as e:
error.text = str(e)
Label:
text = 'Field B'
IntField: fld_b:
value << model.b
value ::
error.text = ''
try:
model.b = change['value']
except ValueError as e:
error.text = str(e)
Label:
text << 'A:{} B:{}'.format(model.a, model.b)
Label: error:
pass
请注意,输出模型值的标签永远不会处于无效状态!模型上的验证器将确保这永远不会发生。
推荐阅读
- javascript - 如何在画布上嵌入图像 (HTML/JS)
- python - 创建数据库时需要使用 commit() 吗?我把它放在哪里?
- 3d - 如何在 mapbox 中添加离线 3D 城市白色模型
- firebase - 作为 bazel 构建的一部分部署 firebase 功能 / ui
- ruby - 无法在 Ruby 中正确格式化“添加两个数字”输出(单链表)
- networking - 连接到 IP 不公开的端点
- python - 如何从列表中删除项目并将其添加到同一列表的末尾
- mysql - 从 mysql 数据库生成 pdf 报告(例如个性报告)
- r - 使用 geom_point() 和 geom_line() 的 ggplot 中的图例错误用于多个系列
- reactjs - 如何在反应钩子中实现派生状态