从Grails自定义标记加载静态资源,并处置:'head'

时间:2013-01-16 20:38:48

标签: grails grails-2.0 custom-tags

我正在尝试编写Grails自定义标记(其中包括)触发包含资源,因此<myTags:view name="foo"/>之类的内容会加载,例如js/views/foo.js。我希望它加载disposition: 'head'

我可以使用<r:external/>,但这不会将其放在<head>中,它只会生成内联<script/>标记。我可以使用<r.script/>,但这不允许我引用路径;我必须让我的自定义标签读取文件并将其转储到out

现在,如果foo.js是它自己的模块,我可以做类似的事情:r.require([module: 'foo']),但事实并非如此;部分原因是我不想在ApplicationResources.groovy中声明所有这些文件。但也许我可以ApplicationResources.groovy以编程方式创建模块,通过阅读可用文件 - 可能吗?或者有更好的方法吗?

1 个答案:

答案 0 :(得分:0)

我最终朝着以编程方式ApplicationResources.groovy创建模块的方向前进,因此自定义标记可以使用<r:require/>

这个想法是,对于每个Backbone视图,在web-app/myApp/views下,.js文件中有一个Backbone视图,.handlebars文件中有一个Handlebars模板(同名,按照惯例)。 .handlebars文件被声明为普通模块,但是由Handlebars-Resources插件预编译。

ApplicationResources.groovy中的一些代码查找所有视图并创建相应的资源模块:

GrailsApplication grailsApplication = Holders.getGrailsApplication()
File viewsDir = grailsApplication.parentContext.getResource("myApp/views").file;
if (viewsDir.exists() && viewsDir.isDirectory() && viewsDir.canRead()) {
    String[] viewsJS = viewsDir.list().findAll { name -> 
        name.endsWith("View.js") 
    }
    String[] views = viewsJS.collect { name ->
        name.substring(0, name.length() - ".js".length())
    }

    for (view in views) {
        "${view}" {
            dependsOn 'backbone', 'backbone_relational', 'handlebars'
            resource url: "dpg/views/${view}.handlebars", 
                     attrs: [type: 'js'], 
                     disposition: 'head'
            resource url: "dpg/views/${view}.js", 
                     disposition: 'head'

        }
    }
}

然后是taglib:

class ViewsTagLib {
    static namespace = "myApp"

    def view = { attrs ->
        r.require(module: "${attrs.name}View")
        out << "<${attrs.tagName} id='${attrs.id}'></${attrs.tagName}>"
    }
}

在GSP中调用它:

<myApp:view tagName="div" name="foo" id="foo1"/>
<myApp:view tagName="div" name="foo" id="foo2"/>

产地:

<html>
    <head>
        ...
        <!--
            Automagically generated modules (included only once).
            Should put these in the same bundle, but handlebars-resources
            gets confused.
        -->
        <script src="/myApp/static/bundle-bundle_fooView_handlebars.js" 
                type="text/javascript" ></script>
        <script src="/myApp/static/bundle-bundle_fooView_head.js" 
                type="text/javascript" ></script>
    </head>
    <body>
        ...
        <div id="foo1"></div> <!-- backbone placeholder for 1st view instance-->
        <div id="foo2"></div> <!-- backbone placeholder for 2nd view instance-->
    </body>
</html>

它并不漂亮,但是这些混乱大多是隐藏的,它应该大大减少了样板,并且有机会忘记将魔术字符串添加到多个文件中。