首页 > 解决方案 > 如何根据 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。不确定这是否是进行此类验证的方法。

标签: enaml

解决方案


一种方法是将数据分解成一个模型,并让它使用一个观察者来验证成员,当任何一个成员发生变化时都会调用该观察者。

然后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

请注意,输出模型值的标签永远不会处于无效状态!模型上的验证器将确保这永远不会发生。


推荐阅读