我的域对象预订有多个允许为空的属性,因为它们将在对象保存到数据库后稍后设置。
myService.action()的一部分:
booking.properties = params
if (booking.contactFirstname?.length() <= 1) { booking.errors.rejectValue("contactFirstname", "empty") }
if (booking.contactLastname?.length() <= 1) { booking.errors.rejectValue("contactLastname", "empty") }
if (booking.contactPhone?.length() <= 1) { booking.errors.rejectValue("contactPhone", "empty") }
if (booking.contactMobile?.length() <= 1) { booking.errors.rejectValue("contactMobile", "empty") }
if (booking.contactEmail?.length() <= 1) { booking.errors.rejectValue("contactEmail", "empty") }
if (booking.hasErrors() || ! booking.validate()) {
return [success: false, model: booking]
} else {
booking.save(failOnError: true)
return [success: true, model: booking]
}
我的控制器确实:
def result = myService.action(params)
if (result.success) {
flash.success = message(code: "msg.successfullySaved")
redirect(action: "registerEventConfirmation", id: result.model.uid, params: [lang: params.lang], mapping: "paginated")
} else {
flash.error = message(code: "msg.errorSavingCheckFields")
render(view: "registerEventStep3", params: [lang: params.lang], model: [booking: result.model])
我正在使用 hasErrors(bean:booking,field:'contactFirstname','has-error')}
标记错误字段。
如果我现在在textfields中提交没有任何值的表单,则所有字段都是红色的,booking.errors有> 0个错误。
如果我使用firstname提交表单后,booking.errors为NULL且没有标记其他字段。
这是一个Bug吗?我和Grails 2.3.6
其他信息
答案 0 :(得分:1)
现在我完全理解了这种情况,因为我在睡觉时遇到了困难,我想我会给你一个非常简洁的答案,这样你就可以充分理解并正确使用。
首先,我知道创建一个验证bean听起来会有很多工作,所以让我教你如何相对简单地完成它以及为什么它是我的首选方法。
这是我首选的方法,因为当你这样做时
class MyController {
def myAction(Mybean bean) {
// 1. the object allowed into this save action
// are all that is available objects withing MyBean.
// If it has user define but not telephone. Then
// if telephone is passed to myAction it will fail and not recognise
// field
// When declaring Date someField or User user then the params now
// received as bean this way is now actually properly bound
// to the data / domainType declared.
// Meaning user will now be actual user or someField actually Date
}
现在解释如何最好地解决这个问题。创建bean时,只需将实际域类从域文件夹复制到grails 2中的src/groovy/same/package
或grails 3中的src/main/groovy/same/package
将名称/类别或副本从Booking
更改为BookingBean
,以便它具有不同的名称。
将@Validateable
添加到grails 2中的实际BookingBean
之上,或者将实现添加到主类中,例如grails 3中的Class BookingBean implements Validateable {
现在,由于它被复制,所有对象都是相同的,此时控制器的保存将是
class MyController {
def myAction(BookingBean bean) {
Booking booking = new Booking()
// this will save all properties
booking.properties = bean
booking.save()
}
}
但是你有一个特殊的情况,你想在主域类中声明一个瞬态字段而不是
class BookingBean {
def id
String contactFirstname
String contactLastname
boolean secondSave=false
static constraints = {
id(nullable: true, bindable: true)
contactFirstname(nullable:true) //,validator:checkHasValue)
contactLastname(nullable:true) //,validator:checkHasValue)
secondSave(nullable:true,validator:checkHasValue))
}
//use the same validator since it is doing identical check
static checkHasValue={value,obj,errors->
// So if secondSave has a value but contactFirstName
// is null then complain about contactFirstName
// you can see how secondSave gets initialise below
//typical set this to true when you are about to save on 2nd attempt
//then when set run validate() which will hit this block below
// Check all the things you think should have a
// value and reject each field that don't
if (val) {
if ( !obj.contactFirstname) {
errors.rejectValue('contactFirstname',"invalid.contactFirstname")
}
if ( !obj.contactSecondname) {
errors.rejectValue('contactSecondname',"invalid.contactSecondname")
}
//and so on
}
}
所以现在在你的控制器中:
class MyController {
def save1(BookingBean bean) {
Booking booking = new Booking()
// this will save all properties
booking.whatEver = bean.whatEver
booking.save()
// you can choose to validate or not here
// since at this point the secondSave has
// not been set therefore validation not called as yet in the bean
}
//你可能有id,它应该与实际的域类绑定
def save2(BookingBean bean) {
booking.secondSave=true
if (!bean.validate()) {
//this is your errors
//bean.errors.allErrors
return
}
//otherwise out of that loop since it hasn't returned
//manually set each object
booking.contactFirstname=bean.contactFirstName
booking.contactSecondname=bean.contactSecondname
booking.save()
}
}
e2a旁注 - 上面应该回答
在创建之前不要验证它。仅在创建对象后验证它,然后添加值。替代方法可能在您作为第二次检查的一部分运行的验证bean中创建一个函数。 This Example bean未经过验证until formatRequest被称为as seen here
答案 1 :(得分:1)
我没有理解你的问题的具体细节,所以在我刚刚开始研究之前,我会给出一些一般的指导。
不要在validate()之前调用hasErrors()。如果你这样做,Grails不会将你的错误从域限制中移除,你只能使用rejectValue()来自己设置错误。
小心使用rejectValue()。尝试使用域约束设置所有错误。如果您有复杂的约束,请使用验证器语法,偶尔obj.getPersistentValue()可能是您的朋友。
如果仍然需要使用rejectValue(),请了解以后对validate()的任何调用都将从头开始并删除先前的错误。我为此写了一个解决方法(放在你的域对象中)虽然我无法向你保证它是100%好的:
def validateWithErrors(def fields = null) {
def existingErrors = this.errors
def ret = (fields ? this.validate(fields) : this.validate())
existingErrors?.allErrors?.each { error ->
this.errors.rejectValue(error.field, error.code)
}
return (existingErrors?.allErrors ? false : ret)
}