That1guyoverthr
That1guyoverthr

Reputation: 1131

Angular-ui-select parent and child grouping

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

Answers (2)

plong0
plong0

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

Ben Orozco
Ben Orozco

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

Related Questions