Pergunta

Eu tenho uma lista de objetos Team que têm uma propriedade Integer seed. Quero editar todas as sementes das equipes de uma só vez, em um único formulário. Estou certeza que Grails suporta parâmetros indexados, mas não posso fazê-lo funcionar.

Aqui está o que eu tenho, e ele funciona, mas eu estou saltando através de maneira muitos aros e tem de haver uma maneira melhor.

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)
}

Não é horrível? Maneira muito barulho. Como posso fazer algo ao longo das linhas de:

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

Isto é, como faço para mapear params nomeado team[0].seed, team[0].id, team[1].seed, team[1].id a uma lista?

Na Stripes você pode apenas ter uma propriedade List<Team> e ele vai funcionar. Eu não menos esperar de Grails! ; -)

Agradecemos antecipadamente a sua ajuda.

Foi útil?

Solução 2

Eu finalmente descobri como fazer isso sem travessuras.

Esqueça o parâmetro oculto e só usar o ID da equipe no parâmetro semente. No GSP:

<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> 

Em seguida, no controlador:

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

funciona como um encanto.

Outras dicas

params é mais do que um mapa regular, é um GrailsParameterMap que automaticamente constrói estruturas sub-mapa com base na divisão dos nomes de parâmetro por ''. Você pode aproveitar este usando a seguinte 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: não há nenhum [] nos atributos de nome. O controlador é agora muito simples usando alguma magia Grails preto:

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

O primeiro findAll operação filtra todos os parâmetros com um interior ponto. O resto é um mapa de mapas segurando o ID de linha na k eo id e seed em v.

Espero que isso responde sua pergunta.

Em 2015 .... Grails funciona um pouco diferente agora e você pode encontrar-se correndo para cordas em vez do esperado sub-maps.I tem algo a trabalho, fazendo
algo como ..

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

EDIT: By The Way ...

entradas que têm o mesmo nome, como

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

são colocados em uma lista se mais de um são submetidos. Então, se ambas as perguntas acima foram verificados

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

Você deseja obter uma lista.

Mas se apenas um está marcada, você NÃO obtiver uma lista (pelo menos em grails verison eu uso), você recebe um valor único.

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

Isso significa que em um controlador, se eu fosse fazer algo como

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

Seria lançar um erro se apenas um item foi enviado. Uma maneira Groovy de contornar este problema é

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

Se o parâmetro é conjunto e não uma lista, ele coloca o valor na lista vazia; Se o parâmetro é definido e uma lista, o operador mais irá adicionar todos os valores individuais para a lista vazia; se o parâmetro não for definido, ele irá adicionar duas listas vazias juntos, o que cria uma única lista vazia.

Não sei se isso ajuda, mas você poderia usar um fecho com ele como:

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

Você provavelmente poderia construir uma lista a partir deste instaed de produzir html. ou construir o seu formulário com ele.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top