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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 02:32:07