我正在尝试用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上很新,所以我可能会遗漏一些明显的东西;如果有人能指出我在上面的代码中出了什么问题,或者另外一种方法让这项工作变得非常棒。
谢谢, 奥利弗
答案 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/at
和html/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
节点。