我有两个域类
class Contract {
String number
static hasMany = [statements:Statement]
}
class Statement {
String code
static hasMany = [contracts:Contract]
}
我想在我的gsp中显示所有可用的语句,每个语句旁边都有一个复选框,允许用户选择适用于合同的语句。如下所示:
[ ] Statement Code 1
[ ] Statement Code 2
[ ] Statement Code 3
我从这开始:
<g:each in="${Statement.list()}" var="statement" status="i">
<g:checkBox name="statements[${i}].id" value="${statement.id}" checked="${contractInstance.statements.contains(statement.id)}" />
<label for="statements[${i}]">${statement.code}</label>
</g:each>
但是我无法获得一个已检查语句的列表给控制器(列表中有null
个元素,有重复的语句......)。
知道如何实现这个目标吗?
答案 0 :(得分:6)
这是可能的,但它确实需要一点点黑客攻击。首先,每个复选框必须具有相同的名称,“语句”:
<g:each in="${org.example.Statement.list(sort: 'id', order: 'asc')}" var="statement" status="i">
<g:checkBox name="statements" value="${statement.id}" checked="${contract.statements.contains(statement)}" />
<label for="statements">${statement.content}</label>
</g:each>
其次,在控制器中,您必须在绑定之前删除“_statements”属性:
def contract = Contract.get(params.id)
params.remove "_statements"
bindData contract, params
contract.save(failOnError: true)
复选框支持尚未针对此用例设计,因此需要进行黑客攻击。多选列表框是通常用于此类场景的列表。
答案 1 :(得分:2)
我个人更喜欢在这种情况下获取Id列表。
<g:each var="book" in="${books}">
<g:checkBox name="bookIds" value="${book.id}" ...
</g:each>
命令对象:
class BookCommand {
List<Serializable> bookIds
}
在控制器操作中:
BookCommand bc ->
author.books = Book.getAll(bc.bookIds)
答案 2 :(得分:1)
将复选框更改为此类似的内容。
<g:checkBox name="statements.${statement.id}" value="true" checked="${contractInstance.statements.contains(statement)?:''}" />
然后在控制器中,在params.statements
中,您将获得一个包含已检查语句ID的列表。
另外注意checked属性中的?:''
,最好添加它,因为checked属性中的任何值(甚至是'false')都被解释为已检查。
答案 3 :(得分:0)
您是否将请求直接映射到Contract
?将传入的请求映射到Command object
。
关于映射列表 - 值仅映射到现有元素。我的意思是它无法创建新的列表元素。您需要在映射之前准备它。如果你知道总有3个元素,你可以:
class ContractCommand {
List statements = [
new Statement(),
new Statement(),
new Statement(),
]
}
并将请求映射到此对象