嵌套ng-repeat+Bootstrap折叠面板:$index与ng-init异常排查
解决Bootstrap手风琴结合Angular多层ng-repeat的ID冲突问题
你碰到的问题根源很明确:手风琴面板的ID和触发链接的href属性重复了,导致Bootstrap的折叠组件只能识别第一个匹配的ID,第二个省份下的面板自然就无法正常展开了。
问题分析
看你原来的代码,地区面板的ID是collapse-1-1{{subdivIndex2}},其中subdivIndex2只是当前省份内部地区的$index。比如第一个省份的第一个地区$index是0,第二个省份的第一个地区$index也是0,这就导致两个地区面板的ID完全一样(都是collapse-1-10)。而Bootstrap的折叠功能是依赖全局唯一ID来绑定触发元素和面板的,重复ID会让组件“迷路”,只能响应第一个匹配的元素。
解决方案
要解决这个问题,我们需要把**父层级的索引(也就是省份的索引)**也加入到子面板的ID中,确保每个面板的ID在整个页面是唯一的。同时,还要调整data-parent属性的指向,保证每个省份下的地区手风琴是独立的容器。
修改后的完整代码
HTML部分
<div class="subdiv-wrapper"> <!-- 省份层级手风琴 --> <div class="panel-group" id="province-accordion" ng-repeat="admin in subdivisions" ng-init="provinceIndex = $index"> <div class="panel panel-default"> <div class="panel-heading"> <h4 class="panel-title"> <a data-toggle="collapse" data-parent="#province-accordion" href="#province-collapse-{{provinceIndex}}"> <span class="span-left">{{ admin.province[0].name }}</span> <span class="span-right">{{ admin.province[0].population }}</span> </a> </h4> </div> <div id="province-collapse-{{provinceIndex}}" class="panel-collapse collapse"> <div class="panel-body"> <h3>districts</h3> <!-- 地区层级手风琴,每个省份对应独立的容器 --> <div class="panel-group" id="district-accordion-{{provinceIndex}}"> <div class="panel panel-default" ng-repeat="district in admin.district" ng-init="districtIndex = $index"> <div class="panel-heading"> <h4 class="panel-title"> <a data-toggle="collapse" data-parent="#district-accordion-{{provinceIndex}}" href="#district-collapse-{{provinceIndex}}-{{districtIndex}}"> <span class="span-left">{{ district.name }}</span> <span class="span-right">{{ district.population }}</span> </a> </h4> </div> <div id="district-collapse-{{provinceIndex}}-{{districtIndex}}" class="panel-collapse collapse"> <div class="panel-body"> <div ng-repeat="commune in district.commune"> <span class="span-left">{{ commune.name }}</span> <span class="span-right">{{ commune.population }}</span> </div> </div> </div> </div> </div> </div> </div> </div> </div> </div>
JavaScript控制器数据(结构优化版,可选)
$scope.subdivisions = [ // 省份:Adrar { "province": {"name":"Adrar","population":"123"}, // 简化为单个对象,因为每个条目对应一个省份 "district": [ {"name":"Adrar","population":"123","commune":[{"name":"Adrar","population":"123"},{"name":"Bouda","population":"123"},{"name":"Ouled Ahmed Timmi","population":"123"}]}, {"name":"Aoulef","population":"123","commune":[{"name":"Akabli","population":"123"},{"name":"Aoulef","population":"123"},{"name":"Timokten","population":"123"}]}, {"name":"Aougrout","population":"123","commune":[{"name":"Aougrout","population":"123"},{"name":"Deldoul","population":"123"},{"name":"Metarfa","population":"123"}]} ] }, // 省份:Algiers { "province": {"name":"Algiers","population":"123"}, "district": [ {"name":"Bab El Oued","population":"123","commune":[{"name":"Bab El Oued","population":"123"},{"name":"Casbah","population":"123"},{"name":"Bains Romains","population":"123"}]}, {"name":"Baraki","population":"123","commune":[{"name":"Baraki","population":"123"},{"name":"Les Eucalyptus","population":"123"},{"name":"Sidi Moussa","population":"123"}]}, {"name":"Bir Mourad Raïs","population":"123","commune":[{"name":"Bir Mourad Raïs","population":"123"},{"name":"Hydra","population":"123"},{"name":"Saoula","population":"123"}]} ] } ];
关键修改点说明
唯一ID生成:
- 省份面板ID:
province-collapse-{{provinceIndex}},结合省份的索引确保全局唯一 - 地区面板ID:
district-collapse-{{provinceIndex}}-{{districtIndex}},同时使用省份索引和地区索引,彻底避免ID重复
- 省份面板ID:
独立手风琴容器:
- 每个省份下的地区手风琴容器ID是
district-accordion-{{provinceIndex}},搭配data-parent="#district-accordion-{{provinceIndex}}",保证每个省份内的地区面板只会在自己的容器内工作,不会和其他省份的面板互相干扰
- 每个省份下的地区手风琴容器ID是
数据结构优化(可选):
- 原来的
province是数组,但每个条目只对应一个省份,所以简化为单个对象,这样HTML里可以直接用admin.province.name而不是admin.province[0].name,代码更简洁
- 原来的
这样修改后,每个层级的面板都能独立正常开闭,不会再出现第二个省份面板失效的问题了。
内容的提问来源于stack exchange,提问作者Gryffin
相关产品推荐
相关产品推荐

