You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

HBS自定义isEmpty块助手嵌套{{#each}}无法渲染问题求助

问题:Handlebars自定义isEmpty助手嵌套{{#each}}无法渲染数据

场景说明

我搭建了一个简单的表单输入页面,提交表单后,表单数据会以条目形式展示。

相关代码

路由代码(Express)

const express = require('express');
const router = express.Router();

const view = 'users';

const data = [];

const croute = '/users';
router
    .route(croute)
    .get((req, res) => res.render(view, { udat: data }))
    .post((req, res) => {
        const {name, age} = req.body;

        data.push({name, age});
        console.log(data);
        res.redirect(croute);
    });

module.exports = router;

HBS视图代码

<form action="/users" method="POST">
    <div>
        <label>
            Name: 
        <input type="text" name="name" required/>
        </label>
    </div>
    <div>
        <label>
            Age:
        <input type="number" name="age" required/>
        </label>
    </div>
    <div> <button type="submit"> Submit </button> </div>
</form>

{{#isEmpty udat}} 
    <h4> There are no users yet. Add Some. </h4>
{{else}}
    <table>
        <thead>
            <tr>
                <td> No. </td>
                <td>Name</td>
                <td>Age</td>
            </tr>
        </thead>
        <tbody>
            {{#each udat}}
                <tr>
                    <td>{{@index}}</td>
                    <td>{{name}}</td>
                    <td>{{age}}</td>
                </tr>
            {{/each}}
        </tbody>
    </table>
{{/isEmpty}}

自定义Handlebars块助手代码

hbs.registerHelper('isEmpty', (arg, options) => {         
   return arg.length <= 0 ? options.fn(this) : options.inverse(this);     
});

问题现象

  • 无用户数据时,isEmpty助手的首个分支(提示无用户)能正常渲染;
  • 提交数据后,<thead>部分正常显示,但{{#each}}循环无法渲染用户条目;
  • 直接使用{{#each}}而不嵌套在isEmpty助手内时,能正常展示所有条目。

解决方案

问题出在自定义助手的上下文传递上:调用options.fn(this)和options.inverse(this)时,传递的this是助手自身的上下文,而非模板的原始根上下文,导致{{#each}}无法访问到udat变量。

修改自定义助手代码,通过options.data.root传递模板根上下文:

hbs.registerHelper('isEmpty', (arg, options) => {         
   return arg.length <= 0 ? options.fn(options.data.root) : options.inverse(options.data.root);     
});

原理说明

Handlebars中,options.data.root指向渲染模板时传入的根上下文对象(即本场景中的{ udat: data })。原代码传递的this是助手内部的上下文,嵌套的{{#each}}无法从中获取到udat,因此循环不执行。修改后,嵌套模板能直接访问根上下文里的变量,{{#each}}即可正常渲染数据。


内容的提问来源于stack exchange,提问作者Caleb Jawa Hkun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 18:33:25