本教程将展示如何创建两个选择框,其中第二个选择框的项目受第一个选择框的值的影响。 开发人员通常会遇到这种情况,也称为链式选择。 一个示例是选择一个国家,然后选择一个州。 州的选择应基于选择哪个国家。
样本输出
这是一个示例输出。 我们为类别提供一个选择框,然后为子类别进行选择。 最初,当第一个框上未选择任何项目时,第二个框为空。
当用户选择颜色类别时,子类别将显示不同的颜色选择。
当用户选择“ 形状”类别时,子类别将显示不同的形状选择。
测试域类
在此示例中,有两个域类。
package asia.grails.test
class Category {
static hasMany = [subCategories:SubCategory]
String name
public String toString() {
return name
}
}
package asia.grails.test
class SubCategory {
static belongsTo = Category
Category category
String name
public String toString() {
return name
}
}
这只是简单的一对多关系。
测试数据
我们通过Bootstrap.groovy填充测试数据
import asia.grails.test.Category
import asia.grails.test.SubCategory
class BootStrap {
def init = { servletContext ->
if ( Category.count() == 0 ) {
Category color = new Category(name:'Color').save()
new SubCategory(category:color, name:'Red').save()
new SubCategory(category:color, name:'Green').save()
new SubCategory(category:color, name:'Blue').save()
Category shape = new Category(name:'Shape').save()
new SubCategory(category:shape, name:'Square').save()
new SubCategory(category:shape, name:'Circle').save()
Category size = new Category(name:'Size').save()
new SubCategory(category:size, name:'Small').save()
new SubCategory(category:size, name:'Medium').save()
new SubCategory(category:size, name:'Large').save()
}
}
def destroy = {
}
}
我们将有3个类别:颜色,形状和大小。
连锁选择表
我们显示一个表格。 控制器代码很简单:
package asia.grails.test
class TestController {
def form() {
}
}
form.gsp的内容是这个。
<%@ page import="asia.grails.test.Category" %>
<!DOCTYPE html>
<html>
<head>
<meta name="layout" content="main">
<title>Chained Select Test</title>
<g:javascript library='jquery' />
</head>
<body>
<div>
<b>Category: </b>
<g:select id="category" name="category.id" from="${Category.listOrderByName()}" optionKey="id"
noSelection="[null:' ']"
onchange="categoryChanged(this.value);" />
</div>
<div>
<b>Sub-Category: </b>
<span id="subContainer"></span>
</div>
<script>
function categoryChanged(categoryId) {
<g:remoteFunction controller="test" action="categoryChanged"
update="subContainer"
params="'categoryId='+categoryId"/>
}
</script>
</body>
</html>
第二个选择框通过id = subContainer呈现在范围内。 每当类别更改时,它都会更新( onchange =” categoryChanged(this.value); )。 呈现子类别的方法是通过AJAX调用。 remoteFunction标记可用于异步调用控制器动作。
包括JQuery库也很重要。 这是通过以下GSP代码完成的:
<g:javascript library='jquery' />
从Grails 2.4开始,不推荐使用Grails AJAX标签。 另一种方法是手动编码javascript方法。 这是categoryChanged函数的替代实现。
<script>
function categoryChanged(categoryId) {
jQuery.ajax({type:'POST',data:'categoryId='+categoryId, url:'/forum/test/categoryChanged',success:function(data,textStatus){jQuery('#subContainer').html(data);},error:function(XMLHttpRequest,textStatus,errorThrown){}});
}
</script>
它更长,但仍然直观。
这是控制器代码的其余部分,其中包括将呈现第二个选择框的方法。
package asia.grails.test
class TestController {
def form() {
}
def categoryChanged(long categoryId) {
Category category = Category.get(categoryId)
def subCategories = []
if ( category != null ) {
subCategories = SubCategory.findAllByCategory(category, [order:'name'])
}
render g.select(id:'subCategory', name:'subCategory.id',
from:subCategories, optionKey:'id', noSelection:[null:' ']
)
}
}
控制器的categoryChanged方法由AJAX函数调用。 它返回选择框HTML代码,并使用id = subContainer在跨度内呈现。