5

I'm trying to display a list of data in a hierarchical view. My data looks something like this:

items:[
  {
    "model_id": "1",
    "model_type_id": "1",
    "name": "Parent 1",
    "model_parent_id": ""
  },
  {
    "model_id": "2",
    "model_type_id": "1",
    "name": "Parent 2",
    "model_parent_id": ""
  },
  {
    "model_id": "3",
    "model_type_id": "2",
    "name": "Child 1",
    "model_parent_id": "1"
  },
  {
    "model_id": "4",
    "model_type_id": "2",
    "name": "Child 2",
    "model_parent_id": "2"
  }
]

My controller looks like:

myApp.controller('ModelController', ['$scope', 'ModelFactory',
    function ($scope, ModelFactory) {

        $scope.init = function (id) {
            $scope.brandId = id;
            getModels($scope.brandId);
        };

        function getModels(brandId) {

            ModelFactory.GetModels(brandId)
                .success(function (mdls) {
                    $scope.models = mdls;
                    console.log($scope.mdls);
                })
                .error(function (error) {
                    $scope.status = 'Unable to load model data: ' + error.message;
                    console.log($scope.status);
                });
        };
    }
]);

My HTML looks like:

<div ng-controller="ModelController" ng-init="init(brand.ID)">
    <ul ng-sortable class="block__list block__list_words">
        <li ng-repeat="model in models | filter: {model_type_id:1} ">{{model.model_name}} - {{model.model_id}}

            <div ng-controller="ModelController" ng-init="init(brand.ID)">
                <ul ng-sortable class="block__list block__list_words">
                    <li ng-repeat="m in models | filter: {model_type_id:2} | filter:{model_parent_id:model.model_id}">
                        {{m.model_name}} - {{m.model_parent_id}}
                    </li>
                </ul>
            </div>

        </li>
    </ul>
</div>

The filter isn't working where I'm trying to filter on the inner controller with the outer controller. I'm getting both children displayed below each parent. How can I get it so the parent is displayed, and only the children are displayed where the childs model_parent_id equals the model_id of the parent?

1 Answer 1

2

While I'm not sure whether there is a way to achieve this using filter, the normal way to display nested data is to reorganize the data structure to reflect what you want to display.

items:[
  {
    "model_id": "1",
    "model_type_id": "1",
    "name": "Parent 1",
    "children": [{
      "model_id": "3",
      "model_type_id": "2",
      "name": "Child 1"
    }]
  },
  {
    "model_id": "2",
    "model_type_id": "1",
    "name": "Parent 2",
    "children": [{
      "model_id": "3",
      "model_type_id": "2",
      "name": "Child 2"
    }]
  }
]

And then display them using nested ng-repeat

<ul>
  <li ng-repeat="parent in items">
    {{parent.name}} - {{parent.model_id}}
    <ul>
      <li ng-repeat="child in parent.children">
        {{child.name}} - {{child.model_id}}
      </li>
    </ul>
  </li>
</ul>

Note: There is no need to use nested controllers, just one on the top layer should be enough. If you need to use some shared logic recursively, use a custom directive to replace the li.


To reorganize the data you can do either on the server side or client side. The following shows how to do in client side as we might not have the permission to change the server side API.

$scope.data = [];
angular.forEach(items, function(item) {
    if (item.model_parent_id == "") {
        $scope.data.push(item);
    }  
});

// add all parents first in case some children comes before parent
angular.forEach(items, function(item) {
    if (item.model_parent_id == "") continue;

    // search for parent
    angular.forEach($scope.data, function(parent) {
        if (parent.model_id == item.model_parent_id) {
            if (!parent.children) parent.children = [];
            parent.children.push(item);
        }
    }
});
Sign up to request clarification or add additional context in comments.

2 Comments

That may prove difficult in my situation. The data is stored in the one table in the database. I have a .net app and creating a function to retrieve the data, then store it in a JSON object correctly would be more time consuming than filtering the way I would like.
You can do data processing in javascript after you get the data, I'll add an example after this.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.