Question

J'ai une liste d'objets Team qui ont une propriété Integer seed. Je veux éditer toutes les graines des équipes à la fois, sous une seule forme. Je suis sûr que Grails prend en charge les paramètres indexés, mais je ne parviens pas à le faire fonctionner.

Voici ce que j'ai et cela fonctionne, mais je saute de manière trop d'objectifs et il doit y avoir un meilleur moyen.

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>

contrôleur:

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'est-ce pas horrible? Beaucoup trop de bruit. Comment puis-je faire quelque chose comme:

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

Comment mapper des paramètres nommés team[0].seed, team[0].id, team[1].seed, team[1].id à une liste?

Dans Stripes , vous pouvez simplement avoir une propriété List<Team> et elle fonctionnera simplement. J'attends rien de moins de Grails! ; -)

Merci d'avance pour votre aide.

Était-ce utile?

La solution 2

J'ai enfin compris comment faire cela sans aucune manigance.

Oubliez le paramètre caché et utilisez simplement l'ID de l'équipe dans le paramètre de départ. Dans le 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> 

Ensuite, dans le contrôleur:

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

Fonctionne comme un charme.

Autres conseils

params est plus qu’une carte normale, c’est un GrailsParameterMap qui construit automatiquement des structures de sous-cartes en divisant les noms de paramètres par ".". Vous pouvez en tirer parti en utilisant le gsp suivant:

<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: il n'y a pas de [] dans les attributs de nom. Le contrôleur est maintenant assez simple avec un peu de magie noire Grails:

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

La première opération findAll élimine tous les paramètres avec un point à l'intérieur. Le reste est une carte de cartes contenant l'identifiant de la ligne dans k et les id et seed dans v.

J'espère que cela répond à votre question.

En 2015 .... Grails fonctionne un peu différemment maintenant et vous risquez de vous heurter à des chaînes plutôt qu'aux sous-cartes attendues.J'ai quelque chose à travailler en faisant cela
quelque chose comme ..

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

EDIT: à propos ...

entrées qui portent le même nom, comme

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

Sont mis dans une liste SI plus d'un est soumis. Donc, si les deux éléments ci-dessus ont été cochés

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

Vous obtiendrez une liste.

Mais si vous cochez une seule case, vous n'obtenez PAS de liste (du moins selon la verison que j'utilise), vous n'obtenez qu'une seule valeur.

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

Cela signifie dans un contrôleur, si je devais faire quelque chose comme

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

Cela provoquerait une erreur si un seul élément était soumis. Un moyen génial de contourner ce problème est

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

Si le paramètre est défini et non une liste, il place la valeur dans la liste vide. Si le paramètre est défini et une liste, l'opérateur plus ajoutera toutes les valeurs individuelles à la liste vide; si le paramètre n'est pas défini, il ajoutera deux listes vides ensemble, ce qui créera une seule liste vide.

Je ne suis pas sûr que cela aide, mais vous pouvez utiliser une fermeture comme celle-ci:

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

Vous pourriez probablement créer une liste à partir de cet exemple de sortie du code HTML. ou construisez votre formulaire avec elle.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top