布局也是一个 gsp 视图,根据定义,它负责处理动态视图内容。
但是,直接编辑 gsp 文件并在运行时编译它们并不是一个好习惯。
相反,您可以定义一个域类,其中自定义内容被持久化并从预定义的 gsp 布局加载。
具体来说,您可以定义类似以下域类的内容来保存自定义 Web 元素:
class Module {
Integer positionLeft
Integer positionTop
Integer width
Integer height
String className //CSS class
String border
String borderColor
Integer borderSize
Integer seq
String content
String type
static hasMany = [components: Component] //inner elements within a module
Module parentModule //support nested module structure to ensure flexibility
User owner
}
class Component {
String title
String content
String methodName
String url
String type //I-image,A-attachment,L-external link,T-text,G-graph report,D-data table,R RSS FEED...
String font
String fontFamily
String fontBold
String fontUnderline
String color
String textAlign
String source //uri -- enables ajax call to some method to get dynamic data
Integer seq
}
使用客户端 javascript,该应用程序可以轻松地使用户通过拖动、调整大小、从某些菜单中选择不同的元素类型以及提交给对这些元素执行 CRUD 操作的后端控制器来生成自定义视图。
然后在布局中,将那些自定义的元素一一渲染:
<%@ page import="com.app.Module" %>
<g:each in="${Module.findAllByOwnerAndParentModuleIsNull(session.user,[fetch:[components:'join']]).collect {[
id:it.id,
posLeft:it.posLeft,
posTop:it. posTop,
width:it.width,
height:it.height,
className:it.className,
border:it.border,
borderColor:it.borderColor,
borderSize:it.borderSize,
seq:it.seq,
content:it.content,
type:it.type,
components:it.components,
innerModules:Module.findAllByParentModule(it)
]}}" var="module" status="i">
<div class="${module.className?module.className:''}" style="position: absolute; left: ${module.posLeft}px; top: ${module.posTop}px; width: ${module.width}px; height: ${module.height}px; border: ${module.borderColor} ${module.borderSize?(module.borderSize+'px'):''} ${module.border};">
<g:each in="${module.innerModules}" var="inner">
<div class="${inner.className?inner.className:''}" style="position: absolute; left: ${inner.posLeft-module.posLeft}px; top: ${inner.posTop-module.posTop}px; width: ${inner.width}px; height: ${inner.height}px; border: blue 1px solid;">
<g:render template="/home/module" model="[
module: inner
]"/>
</div>
</g:each>
<g:render template="/home/module" model="[
module: module
]"/>
</div>
</g:each>
这样,每个用户都可以管理其个性化的布局。