Grails 에서의 Ajax

Ajax


grails에서는 ajax를 통신하는 가장 간단한 방법으로는 remoteLink 태그를 통해 ajax 통신을 할 수 있다.

확인주소 : http://localhost:8080/mygrails/book/view
view.gsp의 내용을 아래와 같이 변경한다.

<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR"/>
<meta name="layout" content="main"/>
<title>Insert title here</title>
<g:javascript library="jquery" />
</head>
<body>
  <div class="body">
  
 <div id="message"></div>
<g:remoteLink action="delete" id="1" update="message">
Delete Book
</g:remoteLink>
  
  </div>
</body>

</html>





BookController 의 내용을 아래와 같이 변경한다.

package net.grails.my

class BookController {

   def view = {

   }
   
def delete() {
    //def b = Book.get(params.id)
    //b.delete()
	def id = params.id
    render "Book ${id} was deleted"
} }




실행하면 아래와같이 확인할수있다





Delete Book A Tag가 실제로 렌더링 된 html이다.
클릭하면 ajax 로 요청을 보내고 성공하면 message div 에 html을 할당하는 모습을 볼 수 있다.


<div id="message"></div>
<a href="/mygrails/book/delete/1" onclick="jQuery.ajax({type:'POST', url:'/mygrails/book/delete/1',success:function(data,textStatus){jQuery('#message').html(data);},error:function(XMLHttpRequest,textStatus,errorThrown){}});return false;" id="1">
Delete Book
</a>




Delete Book 클릭 하면 delete action이 실행된다.
delete action에서 리턴받은(response) 데이터를 message div 에 html을 할당 하는 걸 확인할 수 있다.





formRemote 태그를 이용하여 forn 전송을 할 수 도있다.

view.gsp의 내용을 아래와 같이 변경한다.

<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR"/>
<meta name="layout" content="main"/>
<title>Insert title here</title>
<g:javascript library="jquery" />
</head>
<body>
  <div class="body">
  
  <div id="message"></div>
  <div id="error"></div>
  
<g:formRemote url="[controller: 'book', action: 'delete']"  update="[success: 'message', failure: 'error']" name="myForm">
    <input type="hidden" name="id" value="1" />
    <input type="submit" value="Delete Book!" />
</g:formRemote >
  
  </div>
</body>

</html>



form 전송을 위해 submit 버튼과 hidden 으로 이루어져있다.

실제 렌더링 된 html은 아래와같다.


<div id="message"></div>
  <div id="error"></div>
  
<form onsubmit="jQuery.ajax({type:'POST',data:jQuery(this).serialize(), url:'/mygrails/book/delete',success:function(data,textStatus){jQuery('#message').html(data);},error:function(XMLHttpRequest,textStatus,errorThrown){jQuery('#error').html(XMLHttpRequest.responseText);}});return false" method="post" action="/mygrails/book/delete" id="myForm">
    <input type="hidden" name="id" value="1" />
    <input type="submit" value="Delete Book!" />
</form>






onsubmit 이벤트에 ajax 호출이 이루어져있다.

실행하면 아래와같은 모습이다.



Delete Book! 버튼을 클릭하면 결과는 formRemote 와 같다



Content Centric Ajax(컨텐트 중심 ajax)



template을 서버에서 렌더링 하여 html을 response 받을 수 있다.

테스트 시나리오
1. 페이지를 요청한다.
요청주소 : http://localhost:8080/mygrails/book/view/2
2. ajax 로 book의 상세정보가 담긴 template(html)을 요청하여 div에 셋팅한다.
ajax 요청주소 : action : showBook


_bookTemplate.gsp 을 추가하고 내용을 아래와 같이 변경한다


<%@ page contentType="text/html;charset=UTF-8" %>
<div style="background-color:#CCC">
<p>bookTemplate 입니다.</p>
<p>책 이름은  <span style="color:red">${book.title}</span> 입니다.</p>
</div>

 



BookController 의 내용을 아래와 같이 변경한다.


package net.grails.my

class BookController {

   def view = {
   		Book book = new Book();
		   println params.id
		   book.id = params.id.toInteger()
		   
		   [book:book]
   }

def showBook() {
	   		Book book = new Book();
		   book.id = params.id
		   //조회로직
		   book.title = "Groovy in Action"
		   
	render( model: [book: book], template: "bookTemplate")
}
}




view.gsp의 내용을 아래와 같이 변경한다.
<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR"/>
<meta name="layout" content="main"/>
<title>Insert title here</title>
<g:javascript library="jquery" />
</head>
<body>
  <div class="body">
  
  <div id="message"></div>
  <div id="error"></div>
  
<g:remoteLink action="showBook" id="${book.id}"
              update="book${book.id}">Update Book</g:remoteLink>
<div id="book${book.id}">
   <!--existing book mark-up -->
</div>
</div>
</body>

</html>




실행 후 Update Book을 클릭하면 아래와 같이 확인할 수 있다.


showBook action에서는 bookTemplate과 모델을 렌더링하여 reponse 한다


Data Centric Ajax with JSON


ajax 로 요청을 보내고 응답을 json 데이터로 받아서 처리한다.


확인주소 : http://localhost:8080/mygrails/book/view/2
BookController의 내용을 아래와 같이 변경한다.


package net.grails.my
import grails.converters.JSON
class BookController {

   def view = {
   		Book book = new Book();
		   println params.id
		   book.id = params.id.toInteger()
		   
		   [book:book]
   }

def showBook() {
	   		Book book = new Book();
		   book.id = params.id.toInteger()
		   //조회로직
		   book.title = "Groovy in Action".toString()
		   render book as JSON
}
}



Book.groovy의 내용을 아래와 같이 변경한다.

package net.grails.my

class Book {
	String title
    static constraints = {
    }
}





view.gsp의 내용을 아래와 같이 변경한다.


<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR"/>
<meta name="layout" content="main"/>
<title>Insert title here</title>
<g:javascript library="jquery" />
</head>
<body>
  <div class="body">
  
  <g:javascript>
function updateBook(data) {
    $("#book" + data.id + "_title").html( data.title );
}
</g:javascript>
<g:remoteLink action="showBook" id="${book.id}" onSuccess="updateBook(data)">
    Update Book
</g:remoteLink>
<g:set var="bookId">book${book.id}</g:set>
<div id="${bookId}">
    <div id="book${book.id}_title">The Stand</div>
</div>
</div>
</body>

</html>




실행 후 Upadate Book을 클릭하면 아래와 같이 확인할 수 있다



Data Centric Ajax with XML





XML 로 요청을 보내고 응답을 XML 데이터로 받아서 처리한다.
BookController에 임포트를 추가한다.


import grails.converters.XML


showBook의 내용을 아래와 같이 변경한다.


def showBook() {
	   		Book book = new Book();
		   book.id = params.id.toInteger()
		   //조회로직
		   book.title = "Groovy in Action".toString()
		   render book as XML
}




view.gsp
updateBook 의 함수를 아래와 같이 변경한다.
json과는 달리 xml을 파싱하는 부분이 들어간다.

정보 : fiddler같은 웹 디버깅 툴을 이용하여 xml이 어떤 형태로 response 되는지 확인 하면 파싱하기가 수월 할 것이다.


function updateBook(data) {
    var id = $(data).find("book").attr("id");
    $("#book" + id + "_title").html( $(data).find("title").text() );
}





Responding to both Ajax and non-Ajax requests


ajax 요청일때와 ajax 요청이 아닐때 모두 각각 다르게 응답을 줄 수 있다.




def listBooks() {
    def books = Book.list(params)
    if (request.xhr) {
         //ajax 일 경우 처리
    } else {
       //non-ajax 일 경우 처리
    }
}