Angular-ui-select parent and child grouping
I have an array full of parent objects and nested within each parent object I have an array with child objects. Without rebuilding my model, I am struggling to find the best way to use angular-ui-select to create a grouping enabled dropdown select box.
$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 is what I have created so far, but I need a lot of angular-ui-select functionality 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>
source to share
I think you need to flatten your hierarchy into an array.
Something like: http://plnkr.co/edit/ESHmxOqMuIvAYFdNYcV0
Here is the anti-aliasing function I wrote for your example. The properties can 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 );
By using the depth property in the class (i.e. class="depth-{{category.depth}}"
), you can create padding and styles for group headings. You will need to generate CSS for whatever depths you need to maintain.
source to share
It all depends on what you want it to be selected.
If you want to select the parent , you can only use one , and display the nested data like in the second example: 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 can use two to select in a cascade like this example (with regular selections): http://jsfiddle.net/annavester/Zd6uX/ . You can extrapolate it to 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'];
});
BTW I'm not sure if you can use optgroup with ui-select
source to share