Reputation: 2879
I have a complex dataset in JSON that includes location data that is hierarchal in nature, with a parent of region, child obj of state/country/province, and a sub-child obj of cities. I'm trying to filter on each of these data parts.
The filters on the other values (phase and numbers) work correctly, but the location data doesn't. I'm assuming it's because of the hierarchal nature of that data, but I can't find any filtering examples of hierarchal data in Angular to figure out what I'm doing wrong.
Plunkr: http://plnkr.co/edit/vaKU7l?p=preview
var app = angular.module('plunker', ['angular.filter']);
app.controller('MainCtrl', function($scope, $anchorScroll, $location, $http) {
$scope.cart = [];
$scope.addToCart = function(index) {
$scope.cart.push(index);
$scope.cartCount = $scope.cart.length;
}
$scope.activeRow = function(index) {
$scope.selectedRow = index;
$location.hash();
$anchorScroll('anchor-' + index);
}
$scope.gotoAnchor = function(x) {
var newHash = 'anchor' + x;
}
// GET data
$scope.dataObject = data.List;
$scope.locationObject = data.Locations;
});
body{background:#eee;}
div.cart{display:block;height:70px;background:silver;margin-left:20px;width:200px;padding:5px 10px;margin-bottom:20px;margin-top:20px;}
.cart h1{color:#fff;line-height:20px;}
.item-list-wrapper{height:400px;width:90%;border:1px solid #ddd;overflow-y:scroll;margin-left:20px;}
.item-list-wrapper table td{padding:10px;vertical-align:middle;margin-bottom:10px;font-size:12px;}
.item-list{height:auto;width:100%;margin-bottom:10px;box-shadow:0 2px 2px rgba(0,0,0,0.2);border:1px solid #fff;background:#efefe4;}
.col-num{width:100px;}
.col-compound{width:80px;}
.filters{width:100%;clear:both;margin-left:20px;}
.filters select{width:200px;}
.filters column{height:100px;width:200px;display:inline-block;margin:0;padding:0;}
.filters select{display:inline-block;}
.region{font-weight:bolder;}
.state{font-weight:normal;}
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<link data-require="bootstrap@*" data-semver="3.3.5" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" />
<link data-require="bootstrap-css@*" data-semver="3.3.1" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
<link rel="stylesheet" href="angular-ui.min.css" />
<script>
document.write('<base href="' + document.location + '" />');
</script>
<link rel="stylesheet" href="style.css" />
<script data-require="[email protected]" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.7/angular.min.js" data-semver="1.4.7"></script>
<script data-require="[email protected]" data-semver="1.4.7" src="https://code.angularjs.org/1.4.7/angular-messages.js"></script>
<script data-require="ui-bootstrap@*" data-semver="0.13.3" src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.13.1/ui-bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-filter/0.5.7/angular-filter.min.js"></script>
<script src="angular-ui.min.js"></script>
<script src="app.js"></script>
<script src="http://zbl.me/test/103015.js"></script>
<body ng-controller="MainCtrl">
<div ng-view=""></div>
<!--item-list-wrapper -->
<div class="filters">
<h2>Filter results</h2>
<column>
<select name="selectRegion" class="form-control" ng-model="selectRegion" ng-change="europeSelected()" ng-options="location as location.Region for location in locationObject | orderBy: location.Region:reverse">
<option value="">Select Region</option>
</select>
<select name="selectState" class="form-control" ng-disabled="!selectRegion" ng-model="selectState" ng-options="state as state.StateName for state in selectRegion.States">
<option value="">Select State/Province/Country</option>
</select>
<select name="selectCity" class="form-control" ng-disabled="!selectState" ng-model="selectCity" ng-options="city as city.CityName for city in selectState.Cities">
<option value="">Select City</option>
</select>
</column>
<column>
<select name="selectPhase" class="form-control" ng-model="selectPhase" ng-options="data.Phase as data.Phase for data in dataObject | unique: 'Phase' | orderBy: 'Phase' ">
<option value="">Select Phase</option>
</select>
<select name="selectNumber" class="form-control" ng-model="selectNumber" ng-options="data.Number as data.Number for data in dataObject | unique: 'Compound' | orderBy: 'Compound' ">
<option value="">Select Number</option>
</select>
</column>
</div>
<div class="cart">
<h1>Cart: {{cartCount}}</h1></div>
<div class="item-list-wrapper">
<table class="table table-condensed table-hover">
<tr ng-repeat="data in dataObject | filterBy: ['location.Region']: selectRegion | filterBy: ['state.StateName']: selectState | filterBy: ['city.CityName']: selectCity | filterBy:['Phase']: selectPhase | filterBy:['Number']: selectNumber" ng-click="activeRow($index)">
<td class="column">{{data.Phase}}</td>
<td class="column col-num">{{data.Number}}</td>
<td class="column col-compound">{{data.Compound}}</td>
<td>
<span ng-repeat="location in data.Locations track by $index" class="region">{{ location.Region}}:
<span ng-repeat="site in location.Sites | unique: 'State'" class="state">{{site.State}}
</span>
</span>
</td>
<td><a href="" ng-click="addToCart()">Add</a></td>
</tr>
</table>
</div>
</body>
</html>
Upvotes: 2
Views: 1418
Reputation: 1247
There might be a way to do this with just angular, but you can definitely do this with custom filters. Here's an example -
http://plnkr.co/edit/CLLBoJkfMVCgxqzMNjaC?p=preview
.filter('byCountry', function(){
return function(items, location) {
var filtered = [];
if (!location || !items.length) {
return items;
}
items.forEach(function(itemElement, itemIndex) {
itemElement.Locations.forEach(function(locationElement, locationIndex) {
if (locationElement.Region === location.Region) {
filtered.push(itemElement);
return false;
}
});
});
return filtered;
};
})
Upvotes: 2