Angular JS рендерит дерево данных по уровням

0

Это сложная задача для новичка AngularJS, подобного мне, поэтому я хотел бы попросить некоторую помощь или помощь. Поэтому я хочу, чтобы группировать данные через древовидный и древовидный.

Мой текущий код для HTML:

<!DOCTYPE html>
<html>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>

<body>

  <div ng-app="myApp" ng-controller="myCtrl">
      <ul>
          <li ng-repeat="item in list">
              [[ item.code ]]

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

</body>

</html>

Мой текущий код для JS:

var app = angular.module('myApp', []);

app.controller('myCtrl', function($scope) {

    $scope.list = [
        {
            "id": 1,
            "code": "TANK",
            "tree_id": 1,
            "level": 0,
            "parent": null
        },
        {
            "id": 2,
            "code": "OIL",
            "tree_id": 1,
            "level": 1,
            "parent": 1
        },
        {
            "id": 3,
            "code": "CHEM",
            "tree_id": 1,
            "level": 1,
            "parent": 1
        },
        {
            "id": 6,
            "code": "PROD",
            "tree_id": 1,
            "level": 2,
            "parent": 3
        },
        {
            "id": 4,
            "code": "BULK",
            "tree_id": 2,
            "level": 0,
            "parent": null
        },
        {
            "id": 5,
            "code": "LOG",
            "tree_id": 2,
            "level": 1,
            "parent": 4
        }
    ],
});

Если вы проверили $ scope.list, вы можете найти tree_id, level и parent. Так что я действительно хочу достичь, чтобы сгруппировать объекты через древовидный идентификатор, тогда уровень 0 или верхний уровень будет тем, который присутствует, тогда как уровень 1 и выше будут просто сбрасываемым контентом. Предположим, что tree_id служит в качестве группировки между объектом, уровень может рассматриваться как их порядок иерархии, а корень иерархии наследников будет зависеть от целочисленного значения родителя, являющегося идентификатором дерева. Также имейте в виду, что это не ограничивается одной ветвью, но несколькими, гибкими и неограниченными ветвями

Результат должен выглядеть примерно так:

  • БАК
    • CHEM
    • OIL
      • PROD
  • BULK
    • ЖУРНАЛ
  • 0
    Вы можете изменить структуру $scope.list или использовать существующую структуру?
  • 0
    Существующая структура, как есть, на самом деле пришла из ответа API
Теги:
tree

4 ответа

1

Это уже обсуждалось в StackOverFlow. Вы можете использовать следующую ссылку.

Как я могу группировать данные с помощью Углового фильтра?

Используя фильтр groupBy, вы можете получить древовидную структуру.

  • 0
    Здравствуй! Я ценю ответ, но я как бы изменил вопрос на более интересный и сложный. Ответы в вашей ссылке ограничены одним уровнем
1

Вы также можете использовать пользовательские директивы для обработки рекурсивных уровней:

EDIT, чтобы добавить свойства réf в директивы и вашу новую структуру массива

var app = angular.module('myApp', []);

app.directive('collection', function () {
	return {
		restrict : "E",
		replace : true,
        transclude: true,
		scope : {
			collection : '=',
			list : '=',
			coldisplay : '=',
			colfrom : '=',
			colto : '='
		},
		template : "<ul><member ng-repeat='member in collection track by $index' member='member' list='list' coldisplay='coldisplay' colfrom='colfrom' colto='colto'></member></ul>"
	};
});

app.directive('member', function ($compile) {
	return {
		restrict : "E",
		replace : true,
        transclude: true,
		scope : {
			member : '=',
			list : '=',
			coldisplay : '=',
			colfrom : '=',
			colto : '='
		},
		template : "<li>{{member[coldisplay]}}</li>",
		link : function (scope, element, attrs) {
			scope.children = [];
			angular.forEach(scope.list, function (value, key) {
				if (value[scope.colfrom] === scope.member[scope.colto]) {
					this.push(value);
				}
			}, scope.children);

			if (scope.children.length > 0) {
				element.append("<collection collection='children' list='list' coldisplay='coldisplay' colfrom='colfrom' colto='colto'></collection>");
				$compile(element.contents())(scope);
			}
		}
	}
});

app.controller('myCtrl', function ($scope) {

	$scope.list = [{
			"id" : 1,
			"code" : "TANK",
			"tree_id" : 1,
			"level" : 0,
			"parent" : null
		}, {
			"id" : 2,
			"code" : "OIL",
			"tree_id" : 1,
			"level" : 1,
			"parent" : 1
		}, {
			"id" : 3,
			"code" : "CHEM",
			"tree_id" : 1,
			"level" : 1,
			"parent" : 1
		}, {
			"id" : 6,
			"code" : "PROD",
			"tree_id" : 1,
			"level" : 2,
			"parent" : 3
		}, {
			"id" : 4,
			"code" : "BULK",
			"tree_id" : 2,
			"level" : 0,
			"parent" : null
		}
	];

	$scope.rootList = [];

	angular.forEach($scope.list, function (value, key) {
		if (value.parent == null) {
			this.push(value);
		}
	}, $scope.rootList);

})
<html>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>

<body>
  <div ng-app="myApp" ng-controller="myCtrl">
	  <collection collection='rootList' list='list' coldisplay='"code"' colfrom='"parent"' colto='"id"'></collection>
  </div>
</body>
</html>

Вдохновленный https://toddmotto.com/everything-about-custom-filters-in-angular-js/

  • 0
    Идеальный ответ!
  • 0
    Один вопрос, я попытался проверить элементы, а TANK и CHEM находятся внутри элемента span. Откуда появился элемент span?
Показать ещё 3 комментария
0

чтобы исправить вашу проблему, я бы предложил несколько изменений. Прежде всего, поскольку вы получаете данные из API, нам нужно исправить формат, чтобы получить более разумную структуру. Что-то вроде ниже

[{
  id: 1,
  code: "TANK",
  tree_id: 1,
  parent: null,
  children: [{
    id: 3,
    code: "CHEM",
    tree_id: 1,
    parent: 1,
    children: [{
        id: 9,
        code: "PROD",
        tree_id: 1,
        parent: 3
    }]
  }, {
    id: 2,
    code: "OIL",
    tree_id: 1,
    parent: 1,
  }]
}, {
  id: 4,
  code: "BULK",
  tree_id: 2,
  parent: null,
  children: [{
    id: 5,
    code: "LOG",
    tree_id: 2,
    parent: 4,
  }]
}]

Для этого нам нужно написать функцию, как показано ниже

var createObject = function(json) {
    return {
        id: json.id,
        code: json.code,
        tree_id: json.tree_id,
        parent: json.parent,
        children: []
    }
};

var processList = function(temporaryObj) {

    for (var i = 0; i < list.length; i++) {
        if (list[i].parent === temporaryObj.id) {
            temporaryObj.children.push(processList(createObject(list[i])));
        }
    }

    return temporaryObj;
};

var convertList = function(list) {

    var temp = [];
    for (var i = 0; i < list.length; i++) {

        if (list[i].level === 0) {
            temp.push(processList(createObject(list[i])));
        }

    }

    return temp;
};

var newList = convertList(list_from_api);

И после этого нам нужно создать рекурсивную директиву для печати содержимого в пользовательском интерфейсе

app.directive("tree", ['$compile', '$templateCache', function($compile, $templateCache) {
  return {
    type: "E",
    scope: {
      list: "="
    },
    link: function(scope, element, attrs) {
      element.replaceWith( $compile( $templateCache.get('tree.html'))(scope));
    }
  }
}]);

где tree.html приведен ниже

<ul ng-if="list.length > 0">
   <li ng-repeat="item in list">
      <span>{{ item.code }}</span>
      <tree list="item.children"></tree>
   </li>
</ul>

Вы можете обратиться к этой ссылке plunkr для получения более подробной информации https://plnkr.co/edit/8TtgFfgUQd73Du47b7XB?p=preview

0

в угловой groupBy Работа для object не для array. поэтому вы можете сгенерировать это в своем контроллере по мере необходимости.

Я могу показать вам процесс генерации по вашему желанию. Если хотите, попробуйте.

в вашем контроллере вызовите функцию после получения list из api.

    $scope.newList = {parents:[],childs:[]};


    var generateNav = function(parent) {
      $scope.newList.parents.push(parent);
      angular.forEach($scope.list, function(item) {
        if(item.tree_id === parent.tree_id) {
          $scope.newList.childs.push(item);
        }
      })
    };

    var generateNewList = function(list) {
      angular.forEach(list, function(item) {
      if(item.level === 0) {
        generateNav(item);
      }
      });
    };

    // after api cal and get data call this function with your 'list'
    generateNewList($scope.list);

и В html: используется newList

<ul>
          <li ng-repeat="item in newList.parents">
              {{ item.code }}
              <ul>
                <li ng-repeat="child in newList.childs" ng-if="child.tree_id === item.tree_id && item.id!==child.id">{{child.code}}</li>
              </ul>
          </li>
      </ul>

вы можете посетить PLUNKER DEMO LINK

  • 0
    Здравствуй! Я ценю ответ, но я как бы изменил вопрос на более интересный и сложный.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню