angular 级联选择

HTML:

<link rel="stylesheet" href="views/tree/checkbox.css"/> <div class="tree"> <ul> <li ng-repeat="country in vm.countries" ng-class="{closed:country.closed}"> <div> <input type="checkbox" ng-model="country.checked" ng-change="vm.countryChanged(country)" ng-class="{intermediate: vm.isIntermediateCountry(country)}"/> <span ng-click="country.closed=!country.closed"> <span class="glyphicon" ng-class="country.closed?'glyphicon-plus':'glyphicon-minus'"></span> <img ng-src="images/{{country.flag}}"/> {{country.label}} </span> </div> <ul ng-class="{hidden: country.closed}"> <li ng-repeat="province in country.provinces" ng-class="{closed:province.closed}"> <input type="checkbox" ng-model="province.checked" ng-change="vm.provinceChanged(province, country)" ng-class="{intermediate: vm.isIntermediateProvince(province)}"/> <span ng-click="province.closed=!province.closed"> <span class="glyphicon" ng-class="province.closed?'glyphicon-plus':'glyphicon-minus'"></span> {{province.label}} </span> <ul ng-class="{hidden: province.closed}"> <li ng-repeat="city in province.cities"> <label> <input type="checkbox" ng-model="city.checked" ng-change="vm.cityChanged(city, province, country)"/> {{city.label}} </label> </li> </ul> </li> </ul> </li> </ul> </div> <h3>说明</h3> 这是一个使用controller中的逻辑来实现级联复选框的表,可以支持级联选择以及半选中(semi-checked)状态

JS:

'use strict'; angular.module('ngShowcaseApp').controller('ctrl.tree.checkbox', function ($scope, CityData) { var vm = $scope.vm = {}; vm.countries = CityData; vm.countryChanged = function(country) { // 自动选中所有下级 _.each(country.provinces, function(province) { province.checked = country.checked; _.each(province.cities, function(city) { city.checked = country.checked; }); }); }; vm.provinceChanged = function(province, country) { // 自动选中所有下级 _.each(province.cities, function(city) { city.checked = province.checked; }); // 如果有任何一个子节点被选中,则让上级节点也选中 // 注意!checkbox的ng-model只能绑定到逻辑型值,所以不能直接把findWhere的结果赋值过去 country.checked = !!_.findWhere(country.provinces, {checked: true}) }; vm.cityChanged = function(city, province, country) { // 如果有任何一个子节点被选中,则让上级节点也选中 // 注意!checkbox的ng-model只能绑定到逻辑型值,所以不能直接把findWhere的结果赋值过去 province.checked = !!_.findWhere(province.cities, {checked: true}); country.checked = !!_.findWhere(country.provinces, {checked: true}); }; vm.isIntermediateCountry = function(country) { // 是否有任何被选中的节点 var hasChecked = _.find(country.provinces, function(province) { return province.checked && _.findWhere(province.cities, {checked: true}); }); // 是否有任何没有选中的节点 var hasNoChecked = _.find(country.provinces, function(province) { return !province.checked || _.findWhere(province.cities, {checked: false}); }); // 如果同时有选中状态和非选中的节点,则为中间状态 return hasChecked && hasNoChecked; }; vm.isIntermediateProvince = function(province) { var hasChecked = _.findWhere(province.cities, {checked: true}); var hasNoChecked = _.findWhere(province.cities, {checked: false}); return hasChecked && hasNoChecked; }; });

CSS:

.tree li { cursor: pointer; padding-left: 1.3em; } .tree ul { list-style: none; padding-left: 0; } .intermediate { opacity: 0.3; }