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

NestJS+TypeScript使用Handlebars展示DB事件时属性undefined问题排查

在TypeScript版NestJS中使用Handlebars展示数据库事件时属性显示undefined的排查

我在TypeScript版NestJS里尝试用Handlebars展示从数据库获取的事件数组,但每个对象的属性都显示undefined。请帮忙检查事件传递的方式,找出问题所在。


控制器代码

@Get('views/users/events')
async findAllEvents(
  @Req() req: Request,
  @Res() res: Response,
  @Query('page') page: number = 1,
  @Query('limit') limit: number = 10,
  @Query('name') name?: string,
  @Query('type') type?: string,
) {
  try {
    if (req.cookies.user_jwt) {
      return res.redirect('users-events');
    }

    const response = await this.eventsService.findAll(page, limit, name, type);

    // console.log(response.events);
    return res.render('users-events', {events: response.events, current: page, pages: response.pages, messages: req.flash() });

  } catch (error) {
    if (error instanceof NotFoundException) {
      req.flash('error', error.message);
      return res.render('users-events');
    } else {
      console.error('Error retrieving events:', error);
      req.flash('error', error.message);
      return res.render('users-events');
    }
  }
}

服务层findAll方法代码

async findAll(page: number = 1, limit: number = 10, name?: string, type?: string) {
  try {
    const currentDate = new Date();
    const skip = (page - 1) * limit;

    const query: any = { event_date: { $gte: currentDate } };

    if (name || type) {
      query.$or = [];
      if (name) {
        query.$or.push({ event_name: { $regex: new RegExp(name, 'i') } });
      }
      if (type) {
        query.$or.push({ event_type: { $regex: new RegExp(type, 'i') } });
      }
    }

    const events = await this.eventModel
      .find(query)
      .select('_id image_url event_name event_type description location sponsors event_date')
      .skip(skip)
      .limit(limit)
      .exec();

    if (!events || events.length === 0) {
      throw new NotFoundException('There are no upcoming events at this time.');
    }

    // Calculate total pages
    const totalPages = Math.ceil(events.length / limit);

    return {
      message: 'Events retrieved successfully.',
      totalPages: totalPages,
      pages: `${page} of ${totalPages}`,
      events: events,
      statusCode: HttpStatus.OK
    }
  } catch (error) {
    if (error.name === 'NotFoundException') {
      throw new NotFoundException(error);
    } else {
      console.error('Error retrieving events:', error);
      throw new Error('Error retrieving events.');
    }
  }
}

Handlebars模板代码

{{#each events}}
  <p>{{this.event_name}}</p>
  <p>{{this.description}}</p>
  <p>{{this.location}}</p>
  <p>{{this.event_date}}</p>
  <p>{{this._id}}</p>
{{/each}}

{{#each events}}
  <p>{{this.event_name}}</p>
  <p>{{this.description}}</p>
  <p>{{this.location}}</p>
  <p>{{this.event_date}}</p>
  <p>{{this._id}}</p>
{{/each}}

数据库返回的对象数组示例

[
  {
    _id: new ObjectId('65fb4479787dbd450bb0f640'),
    image_url: 'https://res.cloudinary.com/ddl8i/image/upload/v1710922731/aubjuene3kjkiaggenmu.png',
    event_name: 'Dev Fest',
    event_type: 'Tech',
    description: 'Coding is magic',
    location: 'Lagos',
    sponsors: [],
    event_date: 2024-04-04T00:00:00.000Z
  }
]

排查方向与解决方案

1. 转换Mongoose文档为普通JS对象

Mongoose查询返回的是Mongoose文档对象,而非普通JavaScript对象,Handlebars可能无法直接访问其内部属性。在查询时添加.lean()方法,将文档转为普通对象:

const events = await this.eventModel
  .find(query)
  .select('_id image_url event_name event_type description location sponsors event_date')
  .skip(skip)
  .limit(limit)
  .lean() // 添加此行
  .exec();

2. 验证模板属性名与数据库字段匹配

确认模板中的event_name、description等字段名与数据库返回的字段完全一致(包括大小写、下划线),若Mongoose Schema定义了字段别名,需以Schema中的名称为准。

3. 检查传递给模板的events结构

取消控制器中console.log(response.events);的注释,查看控制台输出的数组结构。若输出为Mongoose文档,尝试打印JSON.stringify(response.events),确认属性是否能正常序列化。

4. 简化Handlebars循环上下文

在{{#each events}}循环中,可省略this.直接使用字段名,测试是否能正常显示:

{{#each events}}
  <p>{{event_name}}</p>
  <p>{{description}}</p>
  <p>{{location}}</p>
  <p>{{event_date}}</p>
  <p>{{_id}}</p>
{{/each}}

5. 修复错误分支的模板渲染

catch分支中渲染模板时未传递events参数,会导致循环无数据。可补充空数组参数:

return res.render('users-events', { events: [], current: page, pages: '0 of 0', messages: req.flash() });

内容的提问来源于stack exchange,提问作者Samie Ezealor

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 15:17:12