Grails parametri indicizzati
-
06-07-2019 - |
Domanda
Ho un elenco di Team
oggetti che hanno una proprietà Integer seed
. Voglio modificare tutti i semi delle squadre contemporaneamente, in un'unica forma. Sono sicuro che Grails supporta parametri indicizzati, ma non riesco a farlo funzionare.
Ecco quello che ho, e funziona ma sto saltando attraverso modo troppi cerchi e ci deve essere un modo migliore.
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>
Controller:
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)
}
Non è terribile? Troppo rumore. Come posso fare qualcosa del genere:
params.teams.each { t ->
def team = Team.get(t.id)
team.seed = t.seed
}
Cioè, come posso mappare i parametri denominati team[0].seed
, team[0].id
, team[1].seed
, team[1].id
a un elenco?
In Stripes puoi semplicemente avere una proprietà List<Team>
e funzionerà. Non mi aspetto di meno dal Grails! ; -)
Grazie in anticipo per il tuo aiuto.
Soluzione 2
Alla fine ho capito come farlo senza shenanigans.
Dimentica il parametro nascosto e usa semplicemente l'ID squadra nel parametro seed. Nell'SPG:
<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>
Quindi, nel controller:
params.teams.seeds.each { teamId, seed ->
def team = Team.get(teamId.toInteger())
team.seed = seed.toInteger()
team.save()
}
redirect(action:list)
Funziona come un fascino.
Altri suggerimenti
params
è più di una normale mappa, è una GrailsParameterMap
che costruisce automaticamente strutture di sub-mappe basate sulla divisione dei nomi dei parametri per '.'. Puoi trarne vantaggio usando il seguente 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: non c'è [] negli attributi del nome. Il controller ora è piuttosto semplice usando un po 'di magia nera di Grails:
log.error "params = ${params}"
params.teams.findAll {k,v -> !k.contains(".")}.each { k,v ->
bindData(Team.get(v.id), v)
}
La prima operazione findAll
filtra tutti i parametri con un punto all'interno. Il resto è una mappa di mappe che contiene l'ID riga in k
e id
e seed
in v
.
Spero che questo risponda alla tua domanda.
Nel 2015 ....
Grails ora funziona in modo leggermente diverso e potresti trovarti a imbatterti in stringhe piuttosto che nelle mappe secondarie previste. Ho qualcosa su cui lavorare facendo
|
qualcosa come ..
params.nested.each{
if(!it.getKey().contains('.')){
//to get a map rather than a string...
params.nested[it.getKey()];
}
};
MODIFICA: A proposito ...
input che hanno lo stesso nome, come
<input name="item.choice" type="checkbox" value="3" />
< input name="item.choice" type="checkbox" value="4"/>
Vengono inseriti in un elenco SE ne viene inviato più di uno. Quindi, se entrambi i precedenti sono stati controllati
<input name="item.choice" type="checkbox" value="3" checked />
< input name="item.choice" type="checkbox" value="4" checked/>
Otterresti un elenco.
Ma se viene selezionato solo uno, NON si ottiene un Elenco (almeno nella versione grails che uso), si ottiene un singolo valore.
<input name="item.choice" type="checkbox" value="3" checked />
< input name="item.choice" type="checkbox" value="4" />
Ciò significa che in un controller, se dovessi fare qualcosa del genere
params['item.choice'].each{
def item=Item.get(it)
}
Sarebbe un errore se fosse inviato un solo oggetto. Un modo efficace per aggirare il problema è
([]+(params['item.choice']?:[])).each{
def item=Item.get(it)
}
Se il parametro è impostato e non un elenco, inserisce il valore nell'elenco vuoto; Se il parametro è impostato e un elenco, l'operatore più aggiungerà tutti i singoli valori all'elenco vuoto; se il parametro non è impostato, verranno aggiunti due elenchi vuoti insieme, creando un unico elenco vuoto.
Non sono sicuro se questo aiuta ma potresti usare una chiusura come:
<g:each in="${teams}">
<p>id: ${it.id}</p>
<p>seed: ${it.seed}</p>
</g:each>
Probabilmente potresti creare un elenco da questo instabile di output HTML. o crea il tuo modulo con esso.