2009-11-28 16 views
8

Tengo una lista de objetos Team que tienen una propiedad Integer seed. Quiero editar todas las semillas de los equipos a la vez, en una sola forma. Estoy seguro que Grails admite parámetros indexados, pero no puedo hacer que funcione.Grails indexed parameters

Esto es lo que tengo, y funciona pero estoy saltando a través de manera demasiados aros y tiene que haber una manera mejor.

gsp:

<g:form action="setSeeds"> 
... 
    <g:each in="${teams}" status="i" var="team"> 
    <input type="hidden" name="teams[${i}].id" value="${team.id}"> 
    <input type="text" size="2" name="teams[${i}].seed" value="${team.seed}"> 
    </g:each> 
</g:form> 

controlador:

def setSeeds = { 
    (0..<30).each { i -> 
    def team = Team.get(Integer.parseInt(params["teams[${i}].id"])) 
    team.seed = Integer.parseInt(params["teams[${i}].seed"]) 
    } 
    redirect(action:list) 
} 

¿No es horrible? Demasiado ruido. ¿Cómo puedo hacer algo en la línea de:

params.teams.each { t -> 
    def team = Team.get(t.id) 
    team.seed = t.seed 
} 

Es decir, ¿cómo Mapa params nombrados team[0].seed, team[0].id, team[1].seed, team[1].id a una lista?

En Stripes puede tener una propiedad List<Team> y simplemente funcionará. ¡No espero menos de Grails! ;-)

Gracias de antemano por su ayuda.

Respuesta

6

Finalmente descubrí cómo hacerlo sin engaños.

Olvídese del parámetro oculto y simplemente use la ID del equipo en el parámetro de inicialización. En el SGP:

<g:form action="setSeeds"> 
... 
    <g:each in="${teams}" var="team"> 
    <input type="text" size="2" name="teams.seeds.${team.id}" 
     value="${team.seed}"> 
    </g:each> 
</g:form> 

Luego, en el controlador:

params.teams.seeds.each { teamId, seed -> 
    def team = Team.get(teamId.toInteger()) 
    team.seed = seed.toInteger() 
    team.save() 
} 
redirect(action:list) 

funciona como un encanto.

-1

No estoy seguro si esto ayuda, pero se podía utilizar un cierre con él como:

<g:each in="${teams}"> 
    <p>id: ${it.id}</p> 
    <p>seed: ${it.seed}</p> 
</g:each> 

Probablemente se podría construir una lista de este instaed de dar salida html. o construye tu formulario con eso.

+0

Ya estoy usando un cierre para crear un formulario. La pregunta es, ¿cómo recupero los parámetros indexados en el controlador para construir una lista? – foxdonut

11

params es más que un mapa normal, es un GrailsParameterMap que automáticamente construye estructuras de submapeo basadas en la división de los nombres de los parámetros por '.'. Es posible que tome ventaja de esta mediante la siguiente gsp:

<g:form action="seed"> 
<g:each in="${teams}" status="i" var="team"> 
    <input type="hidden" name="teams.${i}.id" value="${team.id}"> 
    <input type="text" size="2" name="teams.${i}.seed" value="${team.seed}"> 
    </g:each> 
<g:submitButton name="update" value="Update" /> 
</g:form> 

NB: No hay [] en los atributos de nombre. El controlador es ahora bastante simple uso de algún negro magia Grails:

log.error "params = ${params}" 
params.teams.findAll {k,v -> !k.contains(".")}.each { k,v -> 
     bindData(Team.get(v.id), v) 
} 

La primera operación findAll filtra todos los parámetros con un punto en su interior. El resto es un mapa de mapas con el ID de fila en k y id y seed en v.

Espero que esto responda a su pregunta.

+2

Me pregunto si alguien más está teniendo problemas para hacer que esto funcione. Utilizando Grails 1.3.4, en lugar de obtener el submapa esperado obtengo lo que parece una representación de cadena del submapa. Por ejemplo, params.toString() "[filters.1.value: 123, filters: [" 1 ": [" value ":" 123 "]," 1.value ":" 123 "], action: list, controller : usuario] " – bcowdery

+0

Se siente un poco feo, pero funciona. ¡Gracias! –

+0

Sí, estoy teniendo todo tipo de problemas con esto en 2015. Parece que ahora Grails devuelve todos los valores de los parámetros como cadenas, lo que hace que la cadena 'maplist' sea prácticamente inútil como descubrió bcowdery hace años. – user2782001

1

En 2015 .... Griales funciona un poco diferente ahora y usted puede encontrarse corriendo en cadenas en lugar de la espera sub-maps.I tiene algo para trabajar haciendo
algo así ..

params.nested.each{ 
       if(!it.getKey().contains('.')){ 
       //to get a map rather than a string...  
        params.nested[it.getKey()]; 
       } 
      }; 

EDIT: por cierto ...

insumos que tienen el mismo nombre, como

<input name="item.choice" type="checkbox" value="3" /> 
    < input name="item.choice" type="checkbox" value="4"/> 

Se ponen en una lista SI se envían más de uno. Por lo tanto, si se verificaron ambos de los anteriores

<input name="item.choice" type="checkbox" value="3" checked /> 
    < input name="item.choice" type="checkbox" value="4" checked/> 

Obtendrá una lista.

Pero si solo se comprueba que NO se obtiene una Lista (al menos en la versión de grail que uso), se obtiene un único valor.

 <input name="item.choice" type="checkbox" value="3" checked /> 
    < input name="item.choice" type="checkbox" value="4" /> 

Eso significa que en un controlador, si tuviera que hacer algo como

params['item.choice'].each{ 
      def item=Item.get(it) 
    } 

Sería un error si se presentó un solo elemento. Una manera maravillosa de evitar esto es

([]+(params['item.choice']?:[])).each{ 
     def item=Item.get(it) 
} 

Si el parámetro está establecido y no una lista, que pone el valor en la lista vacía; Si el parámetro está establecido y una lista, el operador más agregará todos los valores individuales a la lista vacía; si el parámetro no está establecido, agregará dos listas vacías juntas, lo que crea una única lista vacía.

+0

¿Alguna idea de por qué es este el caso? ¿Por qué los submapas anidados están rotos? – U47