当我提交表单时,如果我没有为我的单选框选择值,那么不会将任何内容发送到我的命令对象进行验证。 我对文本字段或其他输入类型没有问题。
class ApplicationCommand implements Validateable {
Map<String,String[]> questions = new LinkedHashMap<String,String[]>();
static constraints = {
questions validator: {val, obj, errors ->
for(String key : val.keySet()) {
errors.rejectValue("questions[${key}]",'required');
}
}
}
}
<g:radioGroup name="cmd.questions[1]" values="['Yes']" labels="['Yes']">
${it.radio}${it.label}
</g:radioGroup>
<g:textField name="cmd.questions[2]" />
使用上面的示例,如果我将两个字段都留空并提交,我会得到以下内容
qusetions = [2: String[0]]
我期望看到的是
questions = [1: String[0], 2: String[0]]
由于这个问题,在我的questions validator
中,由于key=1
没有填充,我无法验证它。 这些问题都是动态的,都是从数据库中提取的,所以我无法在验证器中对任何内容进行硬编码,例如if !questions.contains(1)
。 无论提交时将任何数据填充到questions
中,我都必须假设数据是。
我找到了 2 种解决方法,我都不喜欢
1) 仅对于单选按钮,添加一个隐藏字段,如果未选择单选按钮,该字段将强制填充值。 丑陋得可怕
<g:hiddenField name="cmd.questions[1]" value="-" />
2)在我的验证器中,我查询数据库以获取我的所有问题,并手动检查questions
图中是否存在每个问题。 我想避免验证器中的数据库查询。
因此,虽然我的 2 个解决方法确实有效,但我觉得我不应该求助于它们。
认为这是命令对象或圣杯的限制;我认为这是HTML的限制。我看到同样的问题在 PHP 中弹出。
根本问题是你的命令对象不知道有多少问题,但负责确保它们都在那里。我可以想到几种(其他)方法来处理此限制:
快速简便的方法是将带有问题数量的单个隐藏输入放入表单中。也很丑陋,可以由最终用户更改。
另一种选择是将问题提升到域中,以便提前知道问题的数量,并通过字段或方法提供给命令对象。然后,您的命令对象可以询问您的问题,"应该有多少个?好吧,我从风景中得到了那么多吗?这类似于您的 #2,但不必检索整个集合并迭代它。这也打开了对每个问题执行进一步验证的路径(例如,不允许文本进入纯数字答案)。
这确实需要点击数据库,但这是我能想到的在不依赖视图输入的情况下验证问题数量的唯一方法。 好处是你可以让它成为一个非常浅的命中,如果你做得好,击中数据库可以非常快。