Из этого туториала вы узнаете, как создать два поля выбора, в которых на элементы второго блока выбора влияет значение первого. Разработчики сталкиваются с этим обычно, и это также называется цепным выбором. Примером является выбор страны с последующим выбором штата. Выбор штатов должен основываться на том, какая страна была выбрана.
Пример вывода
Вот пример вывода. У нас есть поле выбора для категории с последующим выбором для подкатегории. Первоначально, когда ни один элемент не выбран в первом поле, второй является пустым.
Когда пользователь выбирает категорию цвета , подкатегории будут отображать различные цвета.
Когда пользователь выбирает категорию « Форма» , подкатегории будут отображать различные формы выбора.
Тестовый класс домена
В этом примере есть два класса домена.
1
2
3
4
5
6
7
8
|
package asia.grails.test class Category { static hasMany = [subCategories:SubCategory] String name public String toString() { return name } } |
1
2
3
4
5
6
7
8
9
|
package asia.grails.test class SubCategory { static belongsTo = Category Category category String name public String toString() { return name } } |
Это просто отношения один ко многим.
Тестовые данные
Заполняем тестовые данные через Bootstrap.groovy
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
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 категории: цвет, форма и размер.
Цепная форма выбора
Мы показываем форму. Код контроллера прост:
1
2
3
4
5
|
package asia.grails.test class TestController { def form() { } } |
Содержимое form.gsp это.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
<%@ 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:
1
|
<g:javascript library= 'jquery' /> |
Начиная с Grails 2.4, теги Grails AJAX устарели. Альтернативой является ручное кодирование метода javascript. Вот альтернативная реализация функции categoryChanged.
1
2
3
4
5
|
<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> |
Это длиннее, но все же интуитивно понятно.
Вот остальная часть кода контроллера, который включает метод, который будет отображать второе поле выбора.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
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-код блока выбора и визуализирует его внутри span с id = subContainer .
Ссылка: | Выбор Grails в цепочке — загрузите данные в одном раскрывающемся списке в зависимости от другого от нашего партнера JCG Джонатана Тана в блоге Grails . |