AngularJS中ng-repeat生成的复选框如何正确应用formCheckBox CSS类
AngularJS ng-repeat 渲染的自定义复选框样式不生效问题
问题描述
在AngularJS项目中,需要给ng-repeat渲染的复选框应用自定义formCheckBox CSS类,预期表单加载时自动生成多个带自定义样式的复选框。实际运行时出现复选框消失、样式完全不生效的异常,即便直接给元素设置class="formCheckBox"属性也无法解决。
原有实现代码
HTML
<div require-global-documentvariable="HTML_General_NORM"> <label ng-repeat="fruitName in fruits"> <input ng-class="{'formCheckBox' : fruitName}" type="checkbox" name="selectedFruits[]" value="{{fruitName}}" ng-checked="selection.indexOf(fruitName) > -1" ng-click="toggleSelection(fruitName)" > {{fruitName}} </label> </div>
CSS
.formCheckBox:checked + label::after { content: ''; position: absolute; width: 1.2ex; height: 0.4ex; background: rgba(0, 0, 0, 0); top: 0.9ex; left: 0.4ex; border: 3px solid #2c677d; border-top: none; border-right: none; -webkit-transform: rotate(-45deg); -moz-transform: rotate(-45deg); -o-transform: rotate(-45deg); -ms-transform: rotate(-45deg); transform: rotate(-45deg); } .formCheckBox { line-height: 2.1ex; } .formCheckBox { position: absolute; left: -999em; } .formCheckBox + label { position: relative; overflow: hidden; cursor: pointer; } .formCheckBox + label::before { content: ""; display: inline-block; vertical-align: -25%; height: 2ex; width: 2ex; background-color: white; border: 2px solid #2c677d; border-radius: 4px; box-shadow: inset 0 2px 5px rgba(0,0,0,0.25); margin-right: 0.5em; }
JS
// Fruits $scope.fruits = ['apple', 'orange', 'pear', 'naartjie']; // Selected fruits $scope.selection = ['apple', 'pear']; // Toggle selection for a given fruit by name $scope.toggleSelection = function toggleSelection(fruitName) { var idx = $scope.selection.indexOf(fruitName); // Is currently selected if (idx > -1) { $scope.selection.splice(idx, 1); } // Is newly selected else { $scope.selection.push(fruitName); } $scope.DocumentData.HTML_General_NORM = $scope.selection.join(','); };
故障原因
问题和AngularJS指令、类绑定逻辑无关,核心是DOM结构和CSS选择器规则完全不匹配:
- 自定义CSS中所有label相关样式都使用了
.formCheckBox + label相邻兄弟选择器,该选择器只会匹配紧跟在.formCheckBox元素之后、和它同层级的label元素 - 原有HTML结构中,
<input>是<label>的子元素,二者是嵌套的父子关系,不是同级相邻关系,选择器完全无法命中label元素 - CSS中给
.formCheckBox设置了position: absolute; left: -999em;,会把原生复选框移到屏幕可视区域外,自定义label样式又因为选择器不匹配无法渲染,最终表现为复选框消失、样式完全不生效 - 原有代码中
ng-class="{'formCheckBox' : fruitName}"逻辑本身是正常的,数组内的水果名称都是非空真值,formCheckBox类本来可以正常绑定到input上,不是类绑定失败导致的问题
修复方案
调整HTML结构,让input和label成为同级相邻元素,同时保留点击label选中复选框的交互体验,修复后的HTML代码如下:
<div require-global-documentvariable="HTML_General_NORM"> <div ng-repeat="fruitName in fruits"> <input class="formCheckBox" type="checkbox" id="fruit-{{$index}}" name="selectedFruits[]" value="{{fruitName}}" ng-checked="selection.indexOf(fruitName) > -1" ng-click="toggleSelection(fruitName)" > <label for="fruit-{{$index}}">{{fruitName}}</label> </div> </div>
改动点说明:
- 将
ng-repeat从label上移到外层div,避免label嵌套input - 直接给input加
class="formCheckBox",不需要额外的ng-class条件判断,所有复选框都需要应用该样式 - 借助ng-repeat的
$index内置变量给每个复选框生成唯一id,label通过for属性绑定对应id,保证点击label文字时可以正常切换复选框选中状态,和原嵌套结构的交互体验一致 - input放在label前面,完全匹配CSS中相邻兄弟选择器的规则
调整后CSS的相邻兄弟选择器可以正常命中label元素,自定义复选框样式会正常渲染,原生复选框被移到屏幕外也不会出现“消失”的异常。
内容的提问来源于stack exchange,提问作者Gjustinj
相关产品推荐
相关产品推荐

