Chinese Dynamic Tag Libraries

动态标签库

Grails为JSP和GSP提供了很多内置的标签(见[标签参考]),同时grails也通过他的动态标签库机制提供创建各种自定义标签支持。

Grails的标签的好处在于他不需要任何额外的配置,不需要更新TLD描述,可以在不需要重启服务器进行重新装载。这让你感觉开发标签就像在开发一个页面一样简单,同时具有普通的页面10倍的用处。

警告

Grails 标签库需要一些额外的工作来集成到JSP里去,因为他的动态机制他能无缝的集成到GSP里,如果需要在JSP中使用请参考最后一节。

简单的标签

要创建一个新的标签,修改文件"grails-app/taglib/ApplicationTagLib.groovy",或者创建一个以"TagLib"结尾的新类。 要创建一个简单的标签只需要增加一个新的闭包(closure),这个闭包有一个参数,参数中包含了标签的所有属性:

@Property includeJs = { attrs ->
    out << "<script xsrc='scripts/${attrs['script']}.js' />"
}

要在你的GSP中使用这个标签,只需要使用"g"这个前缀加闭包的名字即可:

<g:includeJs script="myscript" />

逻辑标签

要也可以创建逻辑判断的标签,创建一个使用两个参数的闭包,参数是标签的所有属性和标签的内容:

@Property isAdmin = { attrs, body ->
     def user = attrs['user']
     if(user != null && checkUserPrivs(user)) {
           body()
     }
}

上面的这个标签检查用户是否是管理员,如果是的话就显示标签内的内容:

<g:isAdmin user="${myUser}">
    // 一些有访问权限控制的内容
</g:isAdmin>

迭代标签

当然,你也可以创建迭代(循环)类的标签:

@Property repeat = { attrs, body ->
    def i = Integer.valueOf( attrs["times"] )
    def current = 0
    i.times {
           body( ++current ) // pass the current iteration as the groovy default arg "it"
    }
}

 
要调用你的标签你只需要:

<g:repeat times="3">
<p>Repeat this 3 times! Current repeat = ${it}</p>
</g:repeat>

Markup building in tags

Grails provides a special method that allows building of markup (a common usecase in tags). To do so you invoke the 'mkp' method passing a closure with the markup you want rendered:

@Property dialog = { attrs, body ->
      mkp {
          div('class':'dialog') {
              body()
          }
      }
}

Tags as method calls in GSP

GSP 标签也可以在GSP页面中使用Groovy表达式,例如,hasErrors这个标签可以像普通标签一样使用,如:

<g:hasErrors bean="${book}" field="title">
    <span class='label error'>There were errors on the book title</span>
</g:hasErrors>

也可以当方法调用,如:

<span id="title" class="label ${hasErrors(bean:book,field:'title','errors')}">Title</span>

方法的最后一个参数将被当作标签的标签体,或者你可以传入一个返回字符串的闭包:

<%=
hasErrors(bean:book,field:'title') {
  'errors'
} %>

 在JSP中使用Grails的标签库

要在JSP里使用Grails标签,你可以使用Grails标签库中定义的"invokeTag"标签:

<g:invokeTag name="includeJs" script="myscript" />
<g:invokeTag name="isAdmin" user="${myUser}">
    // some restricted content
</g:invokeTag >
<g:invokeTag name="repeat" times="3">
<p>Repeat this 3 times! Current repeat = <c:out value="${it}" /></p>
</g:invokeTag>

如果你希望你的标签看起来更想普通的JSP标签,你需要:

1) 创建一个新的java类继承 org.codehaus.groovy.grails.web.taglib.jsp.JspInvokeGrailsTagLibTag 并在构造函数中调用"setName()" 方法并传入你的标签名字:

package com.mycompany.taglib;
public class IncludeJsTag extends JspInvokeGrailsTagLibTag {
   public static final String TAG_NAME = "includeJs";
   public IncludeJsTag() {
       super.setName(TAG_NAME);
   }
}

2) JSP 需要在TLD中为每个标签都进行声明,因此你必须根据你的需要修改文件 "web-app/WEB-INF/tld/grails.tld" ,加入你的声明:

<tag>
        <name>includeJs</name>
        <tag-class>com.mycompany.taglib.IncludeJsTag</tag-class>
        <body-content>JSP</body-content>
        <variable>
            <name-given>it</name-given>
            <variable-class>java.lang.Object</variable-class>
            <declare>true</declare>
            <scope>AT_BEGIN</scope>
        </variable>
        <dynamic-attributes>true</dynamic-attributes>
    </tag>

3) 现在,你可以在JSP中想普通的标签一样使用你的新标签了:

<g:includeJs script="myscript" />
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.