【问题标题】:Handlebars Helper to Compare Values (if v1 === v2), and Render Upper-Level Scope?Handlebars Helper 比较值(如果 v1 === v2)并渲染上层范围?
【发布时间】:2014-08-22 19:21:03
【问题描述】:

对于实际通话,我需要这样的东西:

<script id="messagesTemplate" type="text/x-handlebars-template"> 

{{#each messages.messages}}
    {{#each to}}
        {{#ifCond username messages.sessionUserName}}
          <h1>{{username}} is equal to {{messages.sessionUserName}}</h1>
        {{else}}
          <h1>{{username}} is not equal to {{messages.sessionUserName}}</h1>
        {{/ifCond}}
    {{/each}}
{{/each}}

在数据库中,“to”是一个文档数组,每个文档都有一个“用户名”..因此需要 === messages.sessionUserName 来模板/呈现某些值的 HTML(例如 {{# if read.marked}})

"to" : [
    {
        "user" : ObjectId("53aada6f8b10eb0000ec8a90"),
        "username" : "username1",
        "updated" : ISODate("2014-07-01T19:39:45Z"),
        "_id" : ObjectId("53b30e81b0eff5cb1e2ecb21"),
        "read" : {
            "marked" : true
        }
    }
]

值得注意的是,usernameTest 和 sessionUserName 都是通过 express 附加到 res.json() 末尾的值,因此可以通过 messages.usernameTest 和 messages.sessionUserName 访问它们,但它们并不存在于每个文档中......这些值仅在全局父文档中可用。

res.json({
    messages : messages,
    sessionUserName: req.session.username,
    usernameTest: usernameTest
});

这个因素可能是为什么每个都只渲染is equal to,但对第三个(The ../ path segment references the parent template scope)没有意义:

{{#each messages.messages}}
    <h1>{{usernameTest}} is equal to {{sessionUserName}}</h1>
    <h1>{{../usernameTest}} is equal to {{../sessionUserName}}</h1>
    <h1>{{../messages.usernameTest}} is equal to {{../messages.sessionUserName}}</h1>

https://stackoverflow.com/a/9405113/3095287 中提取自定义比较帮助器,{{#ifCond v1 v2}} 之后的模板似乎没有呈现上层作用域元素..

Handlebars.registerHelper('ifCond', function(v1, v2, options) {
  if(v1 === v2) {
    return options.fn(this);
  }
  return options.inverse(this);
});

ifCond 比较确实在 {{#each}} 块之外起作用:

<script id="messagesTemplate" type="text/x-handlebars-template"> 

{{#ifCond messages.usernameTest messages.sessionUserName}}
  <h1>{{messages.usernameTest}} is equal to {{messages.sessionUserName}}</h1>
{{else}}
  <h1>{{messages.usernameTest}} is not equal to {{messages.sessionUserName}}</h1>
{{/ifCond}}

{{#each messages.messages}}
..

.. 呈现:

username1 等于 username1

但是,它在 {{#each}} 块内不起作用:

{{#each messages.messages}}
    {{#ifCond messages.usernameTest messages.sessionUserName}}
      <h1>{{messages.usernameTest}} is equal to {{messages.sessionUserName}}</h1>
    {{else}}
      <h1>{{messages.usernameTest}} is not equal to {{messages.sessionUserName}}</h1>
    {{/ifCond}}
    ...

..因为它只呈现:

等于

即使是 {{../element}}

{{#each messages.messages}}
    {{#ifCond messages.usernameTest messages.sessionUserName}}
      <h1>{{../messages.usernameTest}} is equal to {{../messages.sessionUserName}}</h1>
    {{else}}
      <h1>{{../messages.usernameTest}} is not equal to {{../messages.sessionUserName}}</h1>
    {{/ifCond}}
    ...

..渲染是:

等于

【问题讨论】:

    标签: javascript express helper handlebars.js


    【解决方案1】:

    好的,所以最重要的是您希望能够更深入地访问您的顶级范围。我已经使用客户助手完成了这项工作,该助手在每个块的正常情况下增加了一些额外的内容。

    所以这里是每个普通的把手

        Handlebars.registerHelper('each', function(context, options) {
          var ret = "";
    
          for(var i=0, j=context.length; i<j; i++) {
            ret = ret + options.fn(context[i]);
          }
    
          return ret;
        });
    

    我所做的只是将 'this' 设置为一个名为 root 的属性并将其与结果一起传回。为了克服嵌套循环,我检查我的“root”属性是否存在,如果存在,我将它传递给其他明智的 root = this。

      Handlebars.registerHelper("myEach", function(context, options) {
        var ret = "";
    
        for (var i = 0, j = context.length; i < j; i++) {
            if (this.root) {
                root = this.root;
            } else {
                root = this;
            }
            ret = ret + options.fn(_.extend({}, context[i], {
                root: root
            }));
        }
    
    
        return ret;
    });
    

    现在,无论我的循环有多深,如果我想从根目录使用某些东西,我只需使用 root.property。

    A working codepen can be found here with a simplified version of your example.

    编辑:好的,在发布这篇文章 5 分钟后,我阅读了另一种模板语言的路径,然后意识到车把也有路径。所以您不需要执行上述操作,您只需在模板中使用相对嵌套路径,如下所示。我将继续使用帮助程序,因为我认为使用 root.property 比添加 n 多个“../”更整洁。

    here is a working example using the paths

    <script type="text/x-handlebars-template" id="messages-template">
      Logged in user {{userSession}}
        {{#each messages}}
      <ul>
        <li> Title: {{title}}</li>
        <li> Conetent: {{content}}</li>
        <li> TO:
          <ul>
            {{#each to}}
    
            <li>{{user}} {{#ifvalue user ../../userSession}}
            thats me
            {{else}}
            thats not me
            {{/ifvalue}}</li>
          {{/each}}
          </ul>
        </li>
        </ul>
    
        {{/each}}
    
    
    
    </script>
    

    【讨论】:

    • 谢谢。。不过有一个问题:对于 myEach 助手,ret = ret + options.fn(_.extend({}, context[i], { 导致_ 出现引用错误。有什么建议吗?
    • 哦,是的,它是下划线,我通常使用骨干,所以我总是习惯于使用它。如果您在项目中使用 jQuery,则可以使用 jquery 的扩展: ret = ret + options.fn($.extend(true, context[i], { root: root }))
    • 完美,非常感谢.. 这确实为我们下一阶段的功能奠定了基础......非常感谢
    猜你喜欢
    • 2013-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-22
    • 2017-06-07
    • 2020-04-18
    • 1970-01-01
    相关资源
    最近更新 更多