Reputation: 1131
I have an array full of parent objects, and nested in each parent object I have an array with child objects. Without rebuilding my model I'm struggling to find the best way to use angular-ui-select to achieve a dropdown select box with grouping enabled.
$scope.allCategories = [
{
"code": "AAAA",
"name": "animals",
"categories": [
{
"code": "APET",
"name": "pets"
},
{
"code": "ASUP",
"name": "supplies"
},
{
"code": "AOTH",
"name": "other"
}
]
},
{
"code": "CCCC",
"name": "community",
"categories": [
{
"code": "CCNW",
"name": "classes and workshops"
},
{
"code": "COMM",
"name": "events"
},
{
"code": "CGRP",
"name": "groups"
}
]
}
]
Here's what I've built so far, but I need the many features angular-ui-select has without reinventing the wheel.
<select class="form-control">
<optgroup ng-repeat="category in allCategories" label="{{category.name}}">
<option ng-repeat="childCategory in category.categories" value="{{childCategory.code}}">{{childCategory.name}}</option>
</optgroup>
</select>
Upvotes: 4
Views: 3302
Reputation: 2188
I think you would need to flatten your hierarchy into an array.
Something like: http://plnkr.co/edit/ESHmxOqMuIvAYFdNYcV0
Here is the flattening function I wrote for your example. The properties could be easily adapted for other use cases:
function flattenCategories(categories, depth, parent){
if(angular.isUndefined(depth)){ depth = 1; }
var flat = [];
angular.forEach(categories, function(category){
flat.push({
code: category.code,
name: category.name,
depth: depth,
parent: parent
});
if(category.categories){
var childCategories = flattenCategories(category.categories, depth+1, (angular.isDefined(parent)?parent+'.':'')+category.code);
if(childCategories.length){
flat.push.apply(flat, childCategories);
}
}
});
return flat;
}
$scope.flatCategories = flattenCategories( $scope.allCategories );
Using the depth property in a class (ie. class="depth-{{category.depth}}"
), you can create indents and group header styles. You would need to generate the CSS for however many depths you need to support.
Upvotes: 2
Reputation: 4381
It all depends on what do you want it to be selected.
If you want to select a parent you might use only one select, and display the nested data like in the 2nd example here: http://plnkr.co/edit/a3KlK8dKH3wwiiksDSn2?p=preview
<ui-select-choices repeat="person in people | propsFilter: {name: $select.search, age: $select.search}">
<div ng-bind-html="person.name | highlight: $select.search"></div>
<small>
email: {{person.email}}
age: <span ng-bind-html="''+person.age | highlight: $select.search"></span>
</small>
</ui-select-choices>
if you want to select a child you might use two selects in cascade, like this example (with regular selects): http://jsfiddle.net/annavester/Zd6uX/. You can extrapolate it for ui-select according to your needs
$scope.countries = ['usa', 'canada', 'mexico', 'france'];
$scope.$watch('country', function(newVal) {
if (newVal) $scope.cities = ['Los Angeles', 'San Francisco'];
});
$scope.$watch('city', function(newVal) {
if (newVal) $scope.suburbs = ['SOMA', 'Richmond', 'Sunset'];
});
By the way, I'm not sure if you can use optgroup with ui-select
Upvotes: 0