Статьи

Примеры Grails AJAX

На раннем этапе новички в Grails сталкиваются с отсутствием рабочих образцов, сопровождающих структуру. Хорошие места для примеров и документации включают документацию Grails и блогеров.

Ajax — это одна из функций со встроенной поддержкой Grails. Как только люди «осваивают» основы Grails, они обычно хотят перейти к более интересным функциям, таким как Ajax. Обычно для этого требуется прочесать сеть, найти примеры и / или прочитать документацию достаточно внимательно. Я прошел этот процесс и подумал, что другие могут получить пользу от набора коротких рабочих примеров Ajax в Grails. Я создал небольшое приложение, которое демонстрирует некоторые функции Ajax и предоставляет приложение для загрузки всем, кто заинтересован. (см внизу для скачивания

Информация)

В примере приложения используется каждое из следующего:

  • FormRemote
  • RemoteLink
  • SubmitToRemote
  • RemoteFunction
  • RemoteField

Общие шаги

  • Выберите свою библиотеку JavaScript — прототип, использованный в моем примере. Также показана регистрация некоторых событий Ajax.
01
02
03
04
05
06
07
08
09
10
11
function showSpinner(visible) {
         $('spinner').style.display = visible ? "inline" : "none";
     }
     Ajax.Responders.register({
     onLoading: function() {
           showSpinner(true);
     },
     onComplete: function() {
     if(!Ajax.activeRequestCount) showSpinner(false);
     }
   });
    • Обновите свой контроллер с любым необходимым кодом — ниже весь мой BookController
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package ajax
 
class BookController {
 
     def scaffold = true
 
  def showEditAjax = {
   render (view:'editAjax', model:[bookInstance:Book.get(params.id)])
  }
 
  def showListSelect = {
   render (view:'listSelect', model:[bookInstanceList:Book.list()])
  }
 
  def showTitleSearch = {
   render (view:'titleSearchAjax')
  }
 
  def showRemoteLink = {
   render (view:'remoteLink', model:[bookInstanceList:Book.list()])
  }
 
  def showDetails = {
   render(template:'bookDetails', model:[bookInstance:Book.get(params.id)])
  }
 
  def showSearch = {
   render (view:'searchAjax')
  }
 
  def String wrapSearchParm(value) {
   '%'+value+'%'
  }
 
  def searchTitle = {
   def list = Book.findAllByTitleIlike(wrapSearchParm(params.searchvalue))
   render(template:'searchResults', model:[searchresults:list])
  }
 
  def search = {
   def list
   if (params.publisher && params.title)
    list = Book.findAllByTitleIlikeAndPublisherIlike(wrapSearchParm(params.title), wrapSearchParm(params.publisher))
   else if (params.publisher)
    list = Book.findAllByPublisherIlike(wrapSearchParm(params.publisher))
      else if (params.title)
       list = Book.findAllByTitleIlike(wrapSearchParm(params.title))
 
   render(template:'searchResults', model:[searchresults:list])
  }
 
  def listByPublisher = {
   def list
   if (params.filter.equals("All"))
    list = Book.list()
    else
      list = Book.findAllByPublisher(params.filter)
 
   render(template:'searchResults', model:[searchresults:list])
  }
 
 def update = {
  def bookInstance = Book.get( params.id )
  if(bookInstance) {
   bookInstance.properties = params
   if(!bookInstance.hasErrors() && bookInstance.save()) {
    render "
 Book ${params.title} updated with Ajax using FormRemote"
   }
   else {
    render(view:'edit',model:[bookInstance:bookInstance])
   }
  }
  else {
   flash.message = "Book not found with id ${params.id}"
   redirect(action:edit,id:params.id)
  }
 
  }
 
}
  • Создать / обновить вид (ы) — см. Скриншоты ниже и / или загрузить приложение

Большинство примеров довольно просты и не требуют большого объяснения. Они не могут быть отличными примерами из «реального мира», но их цель — предоставить работающий пример для кого-то, с кого можно начать.

FormRemote

TagLib formRemote создает тег формы, который использует удаленный URI для выполнения вызова AJAX. В этом случае я немного изменил созданный по умолчанию файл edit.gsp, чтобы изменить тег формы на тег formRemote, и добавил div для отображения результатов редактирования. На приведенном ниже снимке экрана показан результат первого нажатия кнопки меню навигации Remote Form, изменения количества страниц в книге «Grails in Action» и нажатия кнопки «Обновить» в нижней части экрана.

RemoteLink

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

1
2
3
<g:each in="${bookInstanceList}" status="i" var="bookInstance">
    <g:remotelink action="showDetails" id="${bookInstance.id}" oncomplete="showSpinner(false);" onloading="showSpinner(true);" update="bookDetails">${fieldValue(bean: bookInstance, field: "title")}</g:remotelink>  
</g:each>

SubmitToRemote

Тег submitToRemote создает кнопку, которая отправляет окружающую форму в виде удаленного вызова Ajax, сериализующего поля в параметры. В примере приложения я создал поля поиска для заголовка и издателя. Кнопка поиска была создана с использованием taglib SubmitToRemote для отправки параметров поиска с помощью Ajax.

1
2
3
4
5
<g:form action="search"><table><tbody>
<tr class="prop">             <td class="name" valign="top">Title:</td>             <td class="value" valign="top"><input name="title" value="${title}" type="text"></td>          </tr>
<tr class="prop">             <td class="name" valign="top">Publisher:</td>             <td class="value" valign="top"><input name="publisher" value="${publisher}" type="text"></td>          </tr>
</tbody>      </table><g:submittoremote oncomplete="showSpinner(false)" onloading="showSpinner(true)" update="searchresults" url="[controller:'book', action:'search']" value="Search">
</g:submittoremote></g:form>

RemoteFunction

Пример приложения использует тег tag Remotebunction для создания удаленной функции JavaScript, которая назначается событию onChange DOM. Когда пользователь выбирает или изменяет значение в раскрывающемся списке «Издатель», вызывается удаленная функция, и в нижней половине экрана отображаются книги, опубликованные выбранным издателем.

RemoteField

В примере приложения используется тег тега RemoteField для создания динамического поиска по названиям книг, аналогично Google Instant. Результаты поиска возвращаются на экран при вводе значений в поле Поиск заголовка. Код контроллера в этом случае оборачивает параметр поиска символом подстановки (%) для поиска в базе данных и возвращает все совпадения, которые будут отображены.

1
2
3
<div id="searchbox">Title Search:
<g:remotefield name="search" oncomplete="showSpinner(false);" onloading="showSpinner(true);" paramname="searchvalue" update="searchresults" url="[controller:'book', action:'searchTitle']">
</g:remotefield></div>

Обнаруженные проблемы

  • Я столкнулся с проблемами, пытаясь заставить корректно показывать счетчик, пока не нашел эту запись в StackOverflow, которая показывала, как регистрировать события Ajax. При локальном запуске в том же окне это происходит очень быстро, поэтому вам действительно нужно следить за правым верхним углом экрана, если вы хотите увидеть счетчик.
  • Я также столкнулся с проблемами с RemoteFunction из-за синтаксических проблем. Будучи привыкшим к тегам тегов, я устанавливал параметр обновления, используя update = ”mydiv”, когда синтаксис должен был обновляться: “mydiv”. Это не помечено как ошибка. Контроллер был вызван, он просто не обновил целевой div!

Загрузки

Было весело собрать это вместе. Надеюсь, это поможет некоторым из вас!

Ссылка: Grails AJAX Примеры от нашего партнера по JCG Майка Миллера в блоге Scratching my itch .