Question

I have a list of categoryTypes and each categoryType has a list of categories within them and i am displaying them in a dropdown which the user can select multiple items from and the choices made will filter what apps are shown in the view (this is an inhouse appstore)

This is the JSON file im working with.

[{"type":"category","id":1181,"categoryType":{"id":1180,"name":"Technology"},"name":"Spotfire"},{"type":"category","id":1182,"categoryType":{"id":1180,"name":"Technology"},"name":"PipelinP"},{"type":"category","id":1184,"categoryType":{"id":1183,"name":"Category"},"name":"IBSI"},{"type":"category","id":1185,"categoryType":{"id":1183,"name":"Category"},"name":"Clin"},{"type":"category","id":1187,"categoryType":{"id":1186,"name":"Capability"},"name":"Chemistry"},{"type":"category","id":1188,"categoryType":{"id":1183,"name":"Category"},"name":"Key Opinion Leaders"},{"type":"category","id":1189,"categoryType":{"id":1183,"name":"Category"},"name":"Pnts"},{"type":"category","id":1190,"categoryType":{"id":1183,"name":"Category"},"name":"CI"},{"type":"category","id":1191,"categoryType":{"id":1180,"name":"Technology"},"name":"VantageP"},{"type":"category","id":1192,"categoryType":{"id":1183,"name":"Category"},"name":"Targets"},{"type":"category","id":1193,"categoryType":{"id":1186,"name":"Capability"},"name":"Information Science"},{"type":"category","id":1194,"categoryType":{"id":1186,"name":"Capability"},"name":"DMP"},{"type":"category","id":1195,"categoryType":{"id":1180,"name":"Technology"},"name":"Spotfire Web Player"},{"type":"category","id":1196,"categoryType":{"id":1186,"name":"Capability"},"name":"PredictiveS"},{"type":"category","id":1198,"categoryType":{"id":1197,"name":"Function"},"name":"PharmD"},{"type":"category","id":1199,"categoryType":{"id":1197,"name":"Function"},"name":"iM - CV/GI"},{"type":"category","id":1200,"categoryType":{"id":1180,"name":"Technology"},"name":"Mobile Apps"},{"type":"category","id":1201,"categoryType":{"id":1197,"name":"Function"},"name":"RAPIDE"},{"type":"category","id":1202,"categoryType":{"id":1197,"name":"Function"},"name":"iM - Oncology"},{"type":"category","id":1203,"categoryType":{"id":1186,"name":"Capability"},"name":"Clin"}]

But because an admin can add categoryTypes and categories to any type the dropdowns need to be dynamically created as they were hard coded. There needs to be a new dropdown for each Category Type.

So what i was able to do was have all categories shown in one dropdown grouped by category type with this;

<select class="form-control"  multiple class="span4 chzn-select" chosen="myCategories" data-placeholder=" "  ng-model="c"  ng-options="c.name group by c.categoryType.name for c in myCategories">

I created the factory to get the categories;

.factory('categoryFactory', function ($resource) {
        return $resource(
                '/resources/appstore/categories'  
        );
    })

The controller looks like this;

$scope.myCategories = [];

  categoryFactory.query(function (d) {
            $scope.myCategories = d;
        });

So for example take the first line of the JSON.

The the category of 'Spotfire' is in the categoryType 'Technology'.

So for that categorytype i would need the dropdown of technology which shows at least spotfire + whatever else is parsed in the JSON file being in that categoryType.

Then another dropdown for the next categoryType and so on.

Was it helpful?

Solution

Here's an alternate version rendering each select individually. It's using a custom groupBy filter (using underscore):

app.filter('groupBy', ['$parse', function ($parse) {
  return function groupByFilter(input, groupByExpr) {
    return _.groupBy(input, $parse(groupByExpr));
  };
}]);

with:

<div ng-repeat="(categoryTypeName, categories) in groupedCategories track by categoryTypeName">
  <label>{{categoryTypeName}}</label>

  <select
    ng-model="selected[categoryTypeName]"
    ng-options="c as c.name for c in categories track by c.id"
    multiple
  ></select>
</div>

Unfortunately the filter has to be applied when the the data changes,

$scope.$watchCollection('categories', function (categories) {
  $scope.groupedCategories = groupByFilter(categories, 'categoryType.name');
});

because if used with ng-repeat directly angular will complain about an Infinite $digest Loop.

Demo: http://plnkr.co/edit/ipfVfH3pbLoYk1u4n3la?p=preview

On the other hand, given your requirements, it would be a lot simpler if your json would already be structured the way you need it (category types with a list of child-categories, not the other way around).


original answer:

I can't really picture your final layout, but a simple starting point could be the group by feature of ng-options.

E.g.:

<select
  ng-model="selected"
  ng-options="c as c.name group by c.categoryType.name for c in categories track by c.id" 
></select>

Demo: http://plnkr.co/edit/JA8DspuVQMRhmKK9YN6r?p=preview

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top