quinta-feira, 22 de agosto de 2013

Grail - Web Layer

- Web Layer

    - Controller
        class BookController {
            static defaultAction = "list"
            def index(){}
            def list() {
                // do controller logic create model
                return model
            }
        }
        - Controllers and Scope
            - servletContext(instance of ServletContext) Also known as application scope, share state across the entire web application.
            - session(HttpSession) - The session allows associating state with a given user and typically uses cookies to associate a session with a client.
            - request(HttpServletRequest) - The request object allows the storage of objects for the current request only.
            - params - Mutable map of incoming request query string or POST parameters
            flash -  make attributes available for this request and the next request only
             def findBy = params["findBy"]       def appContext = request["foo"]         def loggedUser = session["logged_user"]
             def findBy = params.findBy             def appContext = request.foo             def loggedUser = session.logged_user
            flash.message = "User not found for id ${params.id}"
        - Scoped Controllers - static scope = "singleton"
            - prototype (default) - A new controller will be created for each request (recommended for actions as Closure properties)
            - session - One controller is created for the scope of a user session
            - singleton - Only one instance of the controller ever exists (recommended for actions as methods)
            - In Config.groovy defines the default: grails.controllers.defaultScope = "singleton"
        - Models and Views
            - Returning a map:
                def show() {    [book: Book.get(params.id)]    }
            - Returning a ModelAndView
                def index() {
                    // get some books just for the index page, perhaps your favorites
                    def favoriteBooks = ...

                    // forward to the list view to show them
                    return new ModelAndView("/book/list", [ bookList : favoriteBooks ])
                }
            - Selecting a view  (uses a render method)
                class BookController {
                    def show() {
                        def map = [book: Book.get(params.id)]
                        render(view: "display", model: map) //Render the view grails-app/views/book/display.gsp
                        or  render(view: "/shared/display", model: map) // grails-app/views/shared/display.gsp.
                    }
                }
                // render a template to the response for the specified model
                def theShining = new Book(title: 'The Shining', author: 'Stephen King')
                render(template: "book", model: [book: theShining])
                render Book.list(params) as JSON

        - Redirects and Chaining
            - redirect(controller: 'home', action: "next", params: params) // Also redirects to the index action in the home controller
            - redirect(uri: "/login.html") // Redirect to an explicit URI
            - redirect(url: "http://grails.org") // Redirect to a URL
            - class ExampleChainController {
                def first() {    chain(action: second, model: [one: 1])    }
                def second () {    chain(action: third, model: [two: 2] , params: [myparam: "param1"])    }
                def third() {    [three: 3])    }
            }
                result: [one: 1, two: 2, three: 3]
        - Controller Interceptors
            def beforeInterceptor = { println "Tracing action ${actionUri}" }
            or def beforeInterceptor = [action: this.&auth, except: 'login']
                    // defined with private scope, so it's not considered an action
                    private auth() {}
                    def login() { }
        - Data Binding
             def b = new Book(params) // params passed by form.
             or p.properties['firstName','lastName'] = params
             or bindData(p, params, [exclude: 'dateOfBirth'])
             or  def displayInvoice(String accountNumber, int accountType) //with params.accountNumber, and params.accountType
        - XML and JSON
            def results = Book.list()
            render(contentType: "text/xml") { OR render(contentType: "text/json") {
                books {
                    for (b in results) {
                        book(title: b.title)
                }
            }
            OR def result = builder.build {
                categories = ['a', 'b', 'c']
                title = "Hello JSON"
            }
           
        - Upload
            -  def f = request.getFile('myFile')
    - GSP (Groovy Server Page)
        - Scopes
            application - The javax.servlet.ServletContext instance
            applicationContext The Spring ApplicationContext instance
            flash - The flash object
            grailsApplication - The GrailsApplication instance
            out - The response writer for writing to the output stream
            params - The params object for retrieving request parameters
            request - The HttpServletRequest instance
            response - The HttpServletResponse instance
            session - The HttpSession instance
            webRequest - The GrailsWebRequest instance
        - GSP Tags
            <g:example attr="${new Date()}" attr2="[one:1, two:2, three:3]">
               Hello world
            </g:example>
        - Variables and Scope
            <g:set var="now" value="${new Date()}" scope="request" />
        - Logic and iteration
            <g:if test="${session.role == 'admin'}">
               <%-- show administrative functions --%>
            </g:if>
            <g:else>
               <%-- show basic functions --%>
            </g:else>      
            <g:each in="${[1,2,3]}" var="num">
               <p>Number ${num}</p>
            </g:each>
        - Link and Resources
            <g:link controller="book" action="list" id="${currentBook.id} >Book List</g:link>
            <g:link url="[action: 'list', controller: 'book'] params="[sort: 'title', order: 'asc', author: currentBook.author]">Book List</g:link>
        - Form
            <g:form name="myForm" url="[controller:'book',action:'list']">...</g:form>
        - Fields
            textField - For input fields of type 'text'
            passwordField - For input fields of type 'password'
            checkBox - For input fields of type 'checkbox'
            radio - For input fields of type 'radio'
            hiddenField - For input fields of type 'hidden'
            select - For dealing with HTML select boxes
            <g:textField name="myField" value="${myValue}" />
        - Submit
            <g:actionSubmit value="Some update label" action="update" />
        - Tags
            <img src="<g:createLinkTo dir="images" file="logo.jpg" />" />
        - Views and Template
            <g:render template="bookTemplate" model="[book: myBook]" />
            <g:render template="bookTemplate" var="book" collection="${bookList}" />
            can be expressed as <tmpl:bookTemplate book="${myBook}" />
        - Layout in siteMesh (a decorator enginer to support view layouts  grails-app/views/layouts)
            layoutTitle - outputs the target page's title
            layoutHead - outputs the target page's head tag contents
            layoutBody - outputs the target page's body tag contents
            <html>    <head>
                        <title><g:layoutTitle default="An example decorator" /></title>
                        <g:layoutHead />
                    </head>    <body onload="${pageProperty(name:'body.onload')}">
                            <div class="menu"><!--my common menu goes here--></menu>
                                <div class="body">
                                    <g:layoutBody />
                                </div>
                            </div>
                        </body>
            </html>              
            - Server side include
                <g:include controller="book" action="list" />
    - Tag Lib
        Just create a class in  grails-app/taglib
        ex: class SimpleTagLib {
                def emoticon = { attrs, body ->
                   out << body() << (attrs.happy == 'true' ? " :-)" : " :-(")
                }
            }
            in GSP: <g:emoticon happy="true">Hi John</g:emoticon>
           
        ex 2:     def dateFormat = { attrs, body ->
                    out << new java.text.SimpleDateFormat(attrs.format).format(attrs.date)
                }
                <g:dateFormat format="dd-MM-yyyy" date="${new Date()}" />
               
        ex 3:     def isAdmin = { attrs, body ->
                    def user = attrs.user
                    if (user && checkUserPrivs(user)) {
                        out << body()
                    }
                }
                <g:isAdmin user="${myUser}">
                    // some restricted content
                </g:isAdmin>
        - Tags Namespace :     static namespace = "my"    use: <my:example name="..." />
        - JSP Tag Libs
            <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>        <fmt:formatNumber value="${10}" pattern=".00"/>
    - URL Mapping in  grails-app/conf/UrlMappings.groovy
        - ex:
            class UrlMappings {
                static mappings = {    }
            }
        - To Controller and Actions
            "/product"(controller: "product", action: "list").  -> localhost:8080/project/product
        - Variables
            - "/product/$id?"(controller: "product")        ->  localhost:8080/project/product/MacBook // ? shows optional
            - "/$blog/$year/$month/$day/$id"(controller: "blog", action: "show") ->  localhost:8080/project/blogName/2013/10/30/IdValue
            - "/$controller/$action?/$id?"() Dinamic Controller and action
        - Mapping to views
            - "/"(view: "/index")  // map the root URL
            - "403"(controller: "errors", action: "forbidden") or "403"(view: "/errors/forbidden") -> when there is a specific error.
        - To HTTP Methods
            - "/product/$id"(controller:"product") { action = [GET:"show", PUT:"update", DELETE:"delete", POST:"save"]    }
        - It is possible to impose constraints
            - "/$blog/$year?/$month?/$day?/$id?" {
                 controller = "blog"
                 action = "show"
                 constraints {
                      year(matches:/\d{4}/)  //obly to be 4 digits
                      month(matches:/\d{2}/)
                      day(matches:/\d{2}/)
                 }
            }
    - WebFlow (TO DO)
        - Just adds "Flow" at the end of an action.
    - Filters
        - Just create a Class that ends with Filters in grails-app/conf directory.
        all(controller: '*', action: '*') { //Every controller and every action
        justBook(controller: 'book', action: '*') // all actions in controller book.
        notBook(controller: 'book', invert: true)  //every controlelr except BookController
        - Types
            - before
            - after
            - afterView
    - AJAX
        Must add previously int <head> <g:javascript library="jquery" />
        - Remote link
            - <div id="message"></div>
              <div id="error"></div>
              <g:remoteLink update="[success: 'message', failure: 'error']" action="delete" id="1">
                Delete Book
              </g:remoteLink>
            - def delete() {
                def b = Book.get(params.id)
                b.delete()
                render "Book ${b.id} was deleted"
            }
        -  Remote Form Submission
            <g:formRemote url="[controller: 'book', action: 'delete']" update="[success: 'message', failure: 'error']">
                <input type="hidden" name="id" value="1" />
                <input type="submit" value="Delete Book!" />
            </g:formRemote >
            OR
            <form action="delete">
                <input type="hidden" name="id" value="1" />
                <g:submitToRemote action="delete" update="[success: 'message', failure: 'error']" />
            </form>
        - AJAX Events
            - onSuccess - The JavaScript function to call if successful
            - onFailure - The JavaScript function to call if the call failed
            - on_ERROR_CODE - The JavaScript function to call to handle specified error codes (eg on404="alert('not found!')")
            - onUninitialized - The JavaScript function to call the a Ajax engine failed to initialise
            - onLoading - The JavaScript function to call when the remote function is loading the response
            - onLoaded - The JavaScript function to call when the remote function is completed loading the response
            - onComplete - The JavaScript function to call when the remote function is complete, including any updates
        - Ajax on the Server
            - Content Centric Ajax - Where you just use the HTML result of a remote call to update the page
                gsp:
                    <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>
                groovy:
                    render(template: "bookTemplate", model: [book: b])
            - Data Centric Ajax - Where you actually send an XML or JSON response from the server and programmatically update the page
                gsp:
                    <g:javascript>
                        function updateBook(e) {
                            var book = eval("("+e.responseText+")") // evaluate the JSON
                            $("book" + book.id + "_title").innerHTML = book.title
                        }
                    <g:javascript>
                    <g:remoteLink action="test" update="foo" onSuccess="updateBook(e)">
                        Update Book
                    </g:remoteLink>
                    <g:set var="bookId">book${book.id}</g:set>
                    <div id="${bookId}">
                        <div id="${bookId}_title">The Stand</div>
                    </div>
                groovy:
                        def b = Book.get(params.id)
                        render b as JSON
            - Script Centric Ajax - Where the server sends down a stream of JavaScript to be evaluated on the fly
                    def b = Book.get(params.id)
                    response.contentType = "text/javascript"
                    String title = b.title.encodeAsJavascript()
                    render "$('book${b.id}_title')='${title}'"
- Validation
    - Constraints
        static constraints = { }
    - Validating constraints
        def user = new User(params)
        if (user.validate())  ->   else user.errors.allErrors.each { println it   }
    - Validating on the Client
        - <g:renderErrors bean="${user}" />
        or
        - <g:hasErrors bean="${user}">
          <ul>
           <g:eachError var="err" bean="${user}">
               <li>${err}</li>
           </g:eachError>
          </ul>
        </g:hasErrors>
    - Hilight Errors
        <div class='value ${hasErrors(bean:user,field:'login','errors')}'>
            <input type="text" name="login" value="${fieldValue(bean:user,field:'login')}"/>
        </div>

Nenhum comentário:

Postar um comentário