8

我有一个具有属性的Team对象列表。Integer seed我想以单一形式一次编辑所有团队的种子。我确信Grails 支持索引参数,但我无法让它工作。

这就是我所拥有的,它有效,但我跳过了太多的箍,必须有更好的方法。

普惠制:

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

控制器:

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

那不是很可怕吗?噪音太大了。我该如何做一些事情:

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

也就是说,如何将名为team[0].seed, team[0].id, team[1].seed,team[1].id的参数映射到列表?

Stripes中,你可以只拥有一个List<Team>属性,它就可以工作。我对 Grails 的期望也不低!;-)

在此先感谢您的帮助。

4

4 回答 4

11

params不仅仅是一个常规的 Map,它是一个GrailsParameterMap基于“.”分割参数名称自动构建子 Map 结构的工具。您可以通过使用以下 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>

注意:名称属性中没有 []。控制器现在非常简单,使用一些黑色 Grails 魔法:

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

第一个操作findAll过滤掉所有带有点的参数。k其余的是包含行 id in和inid的map 的 map 。seedv

我希望这回答了你的问题。

于 2009-12-02T11:05:49.823 回答
6

我终于想出了如何在没有任何恶作剧的情况下做到这一点。

忘记隐藏参数,只需在种子参数中使用团队 ID。在普惠制中:

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

然后,在控制器中:

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

奇迹般有效。

于 2009-12-09T14:02:38.667 回答
1

在 2015 年.... Grails 现在的工作方式有所不同,您可能会发现自己遇到了字符串而不是预期的子映射。我通过做
类似的事情来工作。

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

编辑:顺便说一句...

具有相同名称的输入,例如

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

如果提交的数量超过一个,则将其放入列表中。所以如果以上两个都被检查了

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

你会得到一份清单。

但是,如果只检查一个,您不会得到一个列表(至少在我使用的 grails 版本中),您会得到一个值。

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

这意味着在控制器中,如果我要做类似的事情

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

如果只提交一个项目,它将引发错误。解决此问题的一种绝妙方法是

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

如果设置了参数而不是列表,则将值放入空列表中;如果设置了参数和列表,加号运算符会将所有单独的值添加到空列表中;如果未设置该参数,它将添加两个空列表,从而创建一个空列表。

于 2015-03-31T17:17:55.190 回答
-1

不确定这是否有帮助,但您可以使用闭包,例如:

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

您可能可以从输出 html 的这个 instaed 中构建一个列表。或用它构建您的表单。

于 2009-11-28T03:58:00.107 回答