Angular 19用@if和@for实现动态Div网格遇NG5002错误求助
Angular 19动态网格布局NG5002错误解决
问题场景
想用Angular 19的@if、@for指令实现动态Div网格:列表有5个项时生成2行,第一行3列、第二行2列,但触发以下错误:
NG5002: Unexpected closing block. The block may have been closed earlier. If you meant to write the } character, you should use the "}" HTML entity instead.
原代码
@for(tool of toolsList.default; track tool.name; let toolsListIdx = $index) { @if(toolsListIdx % 3 == 0) { <div class="row mb-2 text-left"> } <div class="col-sm-4"> <div class="card my-0 py-0 px-3"> <div class="card-body"> <h5 class="text-center">{{ tool.name }}</h5> @for(item of tool.items; track item.name; let idxItem = $index, isLast = $last) { <div class="d-flex align-items-center mb-1"> <input class="cform cform-custom-checkbox-radio col-2" type="checkbox" /> <label class="col-10 mx-1">{{ item.name }}</label> </div> } </div> </div> </div> @if(toolsListIdx % 3 == 2 or isLast) { </div> } }
错误原因
Angular模板编译器要求HTML结构严格嵌套完整,原代码把<div class="row">的开标签和闭标签分别放在两个独立的@if块中,属于“碎片化标签”写法,编译器无法识别合法的块结构,因此抛出NG5002错误。
解决方案
方案1:先分组再遍历(适配Bootstrap row/col)
先在组件逻辑中将工具列表按每3个一组拆分,再在模板中遍历分组生成行:
组件TS代码
get groupedTools() { const groups = []; const tools = this.toolsList.default; for (let i = 0; i < tools.length; i += 3) { groups.push(tools.slice(i, i + 3)); } return groups; }
模板HTML代码
@for(toolGroup of groupedTools; track $index) { <div class="row mb-2 text-left"> @for(tool of toolGroup; track tool.name) { <div class="col-sm-4"> <div class="card my-0 py-0 px-3"> <div class="card-body"> <h5 class="text-center">{{ tool.name }}</h5> @for(item of tool.items; track item.name) { <div class="d-flex align-items-center mb-1"> <input class="cform cform-custom-checkbox-radio col-2" type="checkbox" /> <label class="col-10 mx-1">{{ item.name }}</label> </div> } </div> </div> </div> } </div> }
方案2:用CSS Grid替代Bootstrap布局(更简洁)
放弃拆分row/col的写法,直接用CSS Grid实现自动换行的网格,无需处理分组逻辑:
模板HTML代码
<div class="tool-grid"> @for(tool of toolsList.default; track tool.name) { <div class="tool-card"> <div class="card my-0 py-0 px-3"> <div class="card-body"> <h5 class="text-center">{{ tool.name }}</h5> @for(item of tool.items; track item.name) { <div class="d-flex align-items-center mb-1"> <input class="cform cform-custom-checkbox-radio col-2" type="checkbox" /> <label class="col-10 mx-1">{{ item.name }}</label> </div> } </div> </div> </div> } </div>
配套CSS
.tool-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; /* 替代Bootstrap的mb-2间距 */ margin-bottom: 1rem; } /* 适配小屏幕,自动切换为单列 */ @media (max-width: 768px) { .tool-grid { grid-template-columns: repeat(1, 1fr); } }
内容的提问来源于stack exchange,提问作者Alexdu98
相关产品推荐
相关产品推荐

