无法通过存储在变量中的名称来调用enlive片段

时间:2014-03-02 04:24:34

标签: clojure enlive

我正在尝试用Clojure Enlive lib做一些简单的事情:我希望我的页面的顶层菜单根据用户选择的语言(英语或日语)而有所不同。我找不到如何实现这个基本功能。

我有一个“template / header.html”模板,包含2个部分(每种语言一个):

<div class="header en-US">...</div>
<div class="header ja-JP">...</div>

我在模板代码中创建了2个相应的代码段:

(:require [net.cgrand.enlive-html :as html])
...
(html/defsnippet header-ja-JP "templates/header.html" [:div.header.ja-JP] [])
(html/defsnippet header-en-US "templates/header.html" [:div.header.en-US] [])

现在,当我加载主模板(index.html)时,我想将标题菜单代码填充到导航标记中。

下面,参数'lang'值为“en-US”或“ja-JP”:

(defn process-template
  [lang]
  (let [header-selector  (str “header-“ lang)
        header-content   (@(resolve (symbol header-selector)))]
    (apply str
           (html/emit*
            (html/at
             (html/html-resource "templates/index.html")
             [:nav] (html/content (header-content)))))))

抛出java.lang.NullPointerException

如果我用

替换最后一行
[:nav] (html/content (header-ja-JP)))))))

[:nav] (html/content (header-en-US)))))))

它运行正常(因此代码片段工作),但我尝试了很多不同的语法,无法使动态标头基于语言工作。

如果我在REPL中手动执行上面的代码(让部分)似乎没问题,header-content是包含正确内容的JSON对象,所以我不明白为什么会出现NullPointerException。

理想情况下,我认为我应该只有一个片段将语言作为参数并返回相应的HTML部分,但也没有设法做到这一点。

我在Clojure上很新,所以我可能会遗漏一些明显的东西;如果有人能指出我在上面的代码中出了什么问题,或者另外一种方法让这项工作变得非常棒。

谢谢, 奥利弗

2 个答案:

答案 0 :(得分:0)

您的(@(resolve (symbol header-selector)))会返回一个值。 (resolve (symbol header-selector))返回一个函数。

[:nav] (html/content (header-content)))))))调用header-content作为函数。

(@(resolve (symbol header-selector)))替换为(resolve (symbol header-selector))

我对html/athtml/html-resource这样做很模糊,如果出现其他问题,你可能需要在clojure.java.io/file中填写。

答案 1 :(得分:0)

如果我们想以cgrand建议的方式做不同的事情,那么有许多方法可以实现这一目标。我很难想象他是如何用地图做的,但我会这样做:

(defn process-template [lang]
  (html/select (html/html-snippet
                 "<html>
                    <head></head>
                    <body>
                      <nav>
                        <div class=\"en\"></div>
                        <div class=\"jp\"></div>
                      </nav>
                    </body>
                  </html>") 
        [(keyword (str "div." lang))]))

(apply str (html/emit* (process-template "en")))
=> "<div class=\"en\"></div>"

当然是从文件而不是字符串中的HTML读取它。该函数根据选择器删除匹配的HTML节点。