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>

      

+3


source to share


2 answers


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.

+2


source


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

0


source







All Articles