Reputation: 3987
I'm trying to add the field confirm password to an user register form. This is an extract of my domain class:
package usuario
class Usuario {
transient springSecurityService
String password
String confirmarPassword
static constraints = {
password blank: false, password: true, size:5..15, matches:/[\S]+/
confirmarPassword blank:false, password: true, size:5..15, matches:/[\S]+/, validator:{ val, obj ->
if (obj.password != obj.confirmarPassword)
return 'usuario.password.dontmatch'
}
}
static transients = ['confirmarPassword']
static mapping = {
password column: '`password`'
}
Set<Rol> getAuthorities() {
UsuarioRol.findAllByUsuario(this).collect { it.rol } as Set
}
def beforeInsert() {
encodePassword()
}
def beforeUpdate() {
if (isDirty('password')) {
encodePassword()
}
}
protected void encodePassword() {
password = springSecurityService.encodePassword(password)
}
}
obj.confirmarPassword
is always null so the constraint is never accomplished.
I installed the Grails Templates as it is suggested here. I changed the attribute persistentProperties
, but it is only at _form.gsp, and _form.gsp is not used by Grails Fields Plugins. Therefore, the transients attributes don't appear in the Internet Browser.
I copied the generated transients attributes of the _form.gsp to create.gsp:
<fieldset>
<g:form class="form-horizontal" action="create" >
<div class="fieldcontain ${hasErrors(bean: usuarioInstance, field: 'confirmarPassword', 'error')} required">
<label for="confirmarPassword">
<g:message code="usuario.confirmarPassword.label" default="Confirmar Password" />
<span class="required-indicator">*</span>
</label>
<g:field type="password" name="confirmarPassword" maxlength="15" pattern="${usuarioInstance.constraints.confirmarPassword.matches}" required="" value="${usuarioInstance?.confirmarPassword}"/>
</div>
<fieldset>
<f:all bean="usuarioInstance"/>
<div class="form-actions">
<button type="submit" class="btn btn-primary">
<i class="icon-ok icon-white"></i>
<g:message code="default.button.create.label" default="Create" />
</button>
</div>
</fieldset>
</g:form>
</fieldset>
The transients attributes appear on the screen, but obj.confirmarPassword
is still null
The last approach I thought is to modify views_fields\default_field.gsp to also use these transients attributes, but I didn't find how. This is the documentation. This is the content of that file:
<%@ page defaultCodec="html" %>
<div class="control-group ${invalid ? 'error' : ''}">
<label class="control-label" for="${property}">${label}</label>
<div class="controls">
<%= widget %>
<g:if test="${invalid}"><span class="help-inline">${errors.join('<br>')}</span></g:if>
</div>
</div>
Is it possible with Grails Fields Plugin? Where are the conditions tested, on client or server side? (I think part of the checking is on client side, but all the restrictions are checked again on server side).
Upvotes: 2
Views: 5262
Reputation: 3987
In latest versions of Grails, transient attributes are not binded with form by default. This is the documentation of the bindable constraint. This is how my code would become (I just added bindable: true
):
static constraints = {
password blank: false, password: true, size:5..15, matches:/[\S]+/
confirmarPassword bindable: true, blank:false, password: true, size:5..15, matches:/[\S]+/, validator:{ val, obj ->
if (obj.password != obj.confirmarPassword)
return 'usuario.password.dontmatch'
}
}
However, transient attributes are not shown with <f:all bean="usuarioInstance"/>
, We have to add these attributes manually: <f:field bean="${usuarioInstance}" property="confirmarPassword" />
. It is not an ideal solution. I'll keep this question open some days hoping that someone knows the answer.
UPDATE
In my case, the above solution didn't work either because I'm using Spring Security Core plugin. It gives the next error:
null id in usuario.Usuario entry (don't flush the Session after an exception occurs)
In that case, we have to use a command object. That issue is described (and solved) in this post.
Upvotes: 1
Reputation: 7713
Oh that i have i encountered it before .
Declaring
String confirmarPassword
and making it traniset it doesn't work me like this
static transients = ['confirmarPassword']
But
transient confirmarPassword
As you did it for the springService...i don't now why that doesn't work and this , some one may have a better clarification ...
Upvotes: 1