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
相关产品推荐
相关产品推荐

