Индексируемые параметры Грааля - PullRequest
8 голосов
/ 28 ноября 2009

У меня есть список Team объектов, которые имеют свойство Integer seed. Я хочу редактировать семена всех команд сразу, в одной форме. Я уверен , что Grails поддерживает индексированные параметры, но я не могу заставить его работать.

Вот что у меня есть, и это работает, но я прыгаю через путь слишком много обручей, и должен быть лучший способ.

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>

Контроллер:

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>, и оно будет просто работать. Я ожидаю не меньше от Грааля! ; -)

Заранее спасибо за помощь.

Ответы [ 4 ]

11 голосов
/ 02 декабря 2009

params - это больше, чем обычная карта, это GrailsParameterMap, которая автоматически создает структуры подкарты на основе разделения имен параметров на '.' Вы можете воспользоваться этим, используя следующий 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>

Примечание: в атрибутах имени нет []. Контроллер теперь довольно прост, используя магию черного Грааля:

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

Первая операция findAll отфильтровывает все параметры с точкой внутри. Остальные - это карты, содержащие идентификатор строки в k и id и seed в v.

Надеюсь, это ответит на ваш вопрос.

6 голосов
/ 09 декабря 2009

Я наконец-то понял, как это сделать без всяких махинаций.

Забудьте о скрытом параметре и просто используйте идентификатор команды в параметре seed. В ГСП:

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

Работает как шарм.

1 голос
/ 31 марта 2015

в 2015 году .... Grails теперь работает немного по-другому, и вы можете столкнуться со строками, а не с ожидаемыми вложенными картами. Я получил кое-что для работы, выполнив
что-то вроде ..

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

РЕДАКТИРОВАТЬ: Кстати ... ... 1006 *

входы с одинаковыми именами, например

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

Если параметр задан, а не список, он помещает значение в пустой список; Если задан параметр и список, оператор плюс добавит все отдельные значения в пустой список; если параметр не задан, он добавит два пустых списка вместе, что создаст один пустой список.

0 голосов
/ 28 ноября 2009

Не уверен, поможет ли это, но вы можете использовать закрытие с ним, например:

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

Вы, вероятно, могли бы построить список из этого источника вывода html. или создайте свою форму с ним.

...