def scaffold
class AirlineController { def scaffold = Airline } |
还记得在上一期的文章中说过 def scaffold
的功能是告诉 Grails 在运行的时候动态创建基本的 list()
、save()
和 edit()
方法。它还告诉 Grails 动态创建 GroovyServer Page(GSP)视图。请确保 TripController
和 AirlineController
都包含 def scaffold
。如果曾经因为输入 grails generate-all
在 grails-app/views 中生成过任何 GSP 工件,例如 trip 目录或者是 airline 目录,都应该删除它们。对于这个示例,需要确保既允许 Grails 动态搭建控制器,又允许它动态搭建视图。
更复杂的标记中可以处理属性和标记体。例如,现在的版权标记还需要许多复制/粘贴工作才能满足需求。我想像下面这样将当前的行为放在真正可重用的标记内: <g:copyright startYear="2002">FakeCo Inc.</g:copyright>
。 清单 11 显示了代码:
class DateTagLib { def thisYear = { out << Calendar.getInstance().get(Calendar.YEAR) } def copyright = { attrs, body -> out << "<div id='copyright'>" out << "© ${attrs['startYear']} - ${thisYear()}, ${body()}" out << " All Rights Reserved." out << "</div>" } } |
请注意:attrs
是标记属性的 HashMap
。在这里用它提取 startYear
属性。我将以闭包形式调用 thisYear
标记(这与我用大括号时从 GSP 页面所做的闭包调用相同)。类似地,body
也以闭包的形式传递给标记,所以调用它的方式与调用其他标记的方式相同。这样确保了我的自定义标记可以按照任意深度嵌套到 GSP 中。
您可能注意到,自定义 TagLibs 使用与标准 Grails TagLibs 相同的名称空间 g:
。如果需要将自己的 TagLibs 放在自定义名称空间内,请向 DateTagLib.groovy 中添加 static namespace = 'trip'
。在 GSP 内,TagLib 现在应该是 <trip:copyright startYear="2002">FakeCo Inc.</trip:copyright>
。