簡體   English   中英

將過濾應用於分層結構

[英]Apply filtering to a hierarchical structure

我構建了以下顯示層次結構的Angular應用程序:

我試圖在這個層次結構的頂部插入一個文本框。 過濾底部的數據。 嘗試了幾個帶過濾器的例子但到目前為止運氣不好。

我想要做的是當用戶開始鍵入文本框時使用角度綁定,動態展開和折疊層次結構並突出顯示匹配。

尋找一些建議來解決這個問題的最佳方法。 請注意,層次結構可以變大,並且有大約3000條記錄。

 angular.module('HelloWorldApp', []) .controller('HelloWorldController', function($scope) { $scope.mp6Root = []; $scope.mp6Data = []; var data = [ { "cls": "L2-013551", "clsNm": "FASHION DOLLS", "subCt": "L3-001793", "subCtNm": "FASHION DOLLS AND ACCESSORIES", "ct": "L4-000429", "ctNm": "DOLLS GAMES PUZZLES", "seg": "L5-000031", "segNm": "TOYS", "area": "L6-000004", "areaNm": "HARDLINES" }, { "cls": "L2-006472", "clsNm": "FASHION DOLL WITH ACCS", "subCt": "L3-001793", "subCtNm": "FASHION DOLLS AND ACCESSORIES", "ct": "L4-000429", "ctNm": "DOLLS GAMES PUZZLES", "seg": "L5-000031", "segNm": "TOYS", "area": "L6-000004", "areaNm": "HARDLINES" }, { "cls": "L2-014668", "clsNm": "ACTIVITIES", "subCt": "L3-001793", "subCtNm": "FASHION DOLLS AND ACCESSORIES", "ct": "L4-000429", "ctNm": "DOLLS GAMES PUZZLES", "seg": "L5-000031", "segNm": "TOYS", "area": "L6-000004", "areaNm": "HARDLINES" }, { "cls": "L2-014667", "clsNm": "STORAGE", "subCt": "L3-001793", "subCtNm": "FASHION DOLLS AND ACCESSORIES", "ct": "L4-000429", "ctNm": "DOLLS GAMES PUZZLES", "seg": "L5-000031", "segNm": "TOYS", "area": "L6-000004", "areaNm": "HARDLINES" }, { "cls": "L2-014675", "clsNm": "FASHION DOLL PLAYSET", "subCt": "L3-001793", "subCtNm": "FASHION DOLLS AND ACCESSORIES", "ct": "L4-000429", "ctNm": "DOLLS GAMES PUZZLES", "seg": "L5-000031", "segNm": "TOYS", "area": "L6-000004", "areaNm": "HARDLINES" }, { "cls": "L2-006476", "clsNm": "ROLE PLAY FASHION AND TOY", "subCt": "L3-001793", "subCtNm": "FASHION DOLLS AND ACCESSORIES", "ct": "L4-000429", "ctNm": "DOLLS GAMES PUZZLES", "seg": "L5-000031", "segNm": "TOYS", "area": "L6-000004", "areaNm": "HARDLINES" }, { "cls": "L2-014677", "clsNm": "CORE PS FIGURE W PLAYSET", "subCt": "L3-001798", "subCtNm": "CORE PRESCHOOL TOYS", "ct": "L4-000428", "ctNm": "PRESCHOOL", "seg": "L5-000031", "segNm": "TOYS", "area": "L6-000004", "areaNm": "HARDLINES" }, { "cls": "L2-006508", "clsNm": "CORE PS MUSICAL INSTRUMENT", "subCt": "L3-001798", "subCtNm": "CORE PRESCHOOL TOYS", "ct": "L4-000428", "ctNm": "PRESCHOOL", "seg": "L5-000031", "segNm": "TOYS", "area": "L6-000004", "areaNm": "HARDLINES" }, { "cls": "L2-014788", "clsNm": "WAGONS TOYS", "subCt": "L3-001798", "subCtNm": "CORE PRESCHOOL TOYS", "ct": "L4-000428", "ctNm": "PRESCHOOL", "seg": "L5-000031", "segNm": "TOYS", "area": "L6-000004", "areaNm": "HARDLINES" }, { "cls": "L2-006536", "clsNm": "RIDING TOYS FOOT TO FLOOR", "subCt": "L3-001798", "subCtNm": "CORE PRESCHOOL TOYS", "ct": "L4-000428", "ctNm": "PRESCHOOL", "seg": "L5-000031", "segNm": "TOYS", "area": "L6-000004", "areaNm": "HARDLINES" }, { "cls": "L2-014678", "clsNm": "CORE PS PUZZLE", "subCt": "L3-001798", "subCtNm": "CORE PRESCHOOL TOYS", "ct": "L4-000428", "ctNm": "PRESCHOOL", "seg": "L5-000031", "segNm": "TOYS", "area": "L6-000004", "areaNm": "HARDLINES" }, { "cls": "L2-006506", "clsNm": "CORE PS FIGURE PLAYSET", "subCt": "L3-001798", "subCtNm": "CORE PRESCHOOL TOYS", "ct": "L4-000428", "ctNm": "PRESCHOOL", "seg": "L5-000031", "segNm": "TOYS", "area": "L6-000004", "areaNm": "HARDLINES" }, { "cls": "L2-006509", "clsNm": "CORE PS OTHER TOYS", "subCt": "L3-001798", "subCtNm": "CORE PRESCHOOL TOYS", "ct": "L4-000428", "ctNm": "PRESCHOOL", "seg": "L5-000031", "segNm": "TOYS", "area": "L6-000004", "areaNm": "HARDLINES" }, { "cls": "L2-006511", "clsNm": "CORE PS TALKING SOUND", "subCt": "L3-001798", "subCtNm": "CORE PRESCHOOL TOYS", "ct": "L4-000428", "ctNm": "PRESCHOOL", "seg": "L5-000031", "segNm": "TOYS", "area": "L6-000004", "areaNm": "HARDLINES" }, { "cls": "L2-006507", "clsNm": "CORE PS LEARNING TOY", "subCt": "L3-001798", "subCtNm": "CORE PRESCHOOL TOYS", "ct": "L4-000428", "ctNm": "PRESCHOOL", "seg": "L5-000031", "segNm": "TOYS", "area": "L6-000004", "areaNm": "HARDLINES" }, { "cls": "L2-006510", "clsNm": "CORE PS ROLEPLAY", "subCt": "L3-001798", "subCtNm": "CORE PRESCHOOL TOYS", "ct": "L4-000428", "ctNm": "PRESCHOOL", "seg": "L5-000031", "segNm": "TOYS", "area": "L6-000004", "areaNm": "HARDLINES" }, { "cls": "L2-006512", "clsNm": "CORE PS VEHICLES", "subCt": "L3-001798", "subCtNm": "CORE PRESCHOOL TOYS", "ct": "L4-000428", "ctNm": "PRESCHOOL", "seg": "L5-000031", "segNm": "TOYS", "area": "L6-000004", "areaNm": "HARDLINES" }, { "cls": "L2-006585", "clsNm": "DIECAST MED LG SCALE VEHICLES", "subCt": "L3-001818", "subCtNm": "DIECAST AND PLAYSETS", "ct": "L4-000425", "ctNm": "ACT FIGS CONSTRUCTION VEHICLES", "seg": "L5-000031", "segNm": "TOYS", "area": "L6-000004", "areaNm": "HARDLINES" }, { "cls": "L2-006587", "clsNm": "DIECAST PLAYSETS", "subCt": "L3-001818", "subCtNm": "DIECAST AND PLAYSETS", "ct": "L4-000425", "ctNm": "ACT FIGS CONSTRUCTION VEHICLES", "seg": "L5-000031", "segNm": "TOYS", "area": "L6-000004", "areaNm": "HARDLINES" }, { "cls": "L2-006586", "clsNm": "DIECAST MINI VEHICLES", "subCt": "L3-001818", "subCtNm": "DIECAST AND PLAYSETS", "ct": "L4-000425", "ctNm": "ACT FIGS CONSTRUCTION VEHICLES", "seg": "L5-000031", "segNm": "TOYS", "area": "L6-000004", "areaNm": "HARDLINES" }, { "cls": "L2-006798", "clsNm": "VACUUMS UPRIGHT BAGLESS", "subCt": "L3-001851", "subCtNm": "FLOOR CLEANING", "ct": "L4-000449", "ctNm": "HOME ELECTRICS", "seg": "L5-000054", "segNm": "HARD HOME", "area": "L6-000012", "areaNm": "IN AND OUTDOOR HOME" }, { "cls": "L2-006795", "clsNm": "VACUUMS HAND", "subCt": "L3-001851", "subCtNm": "FLOOR CLEANING", "ct": "L4-000449", "ctNm": "HOME ELECTRICS", "seg": "L5-000054", "segNm": "HARD HOME", "area": "L6-000012", "areaNm": "IN AND OUTDOOR HOME" }, { "cls": "L2-006791", "clsNm": "FLOOR DEEP CLEANER CHEMICALS", "subCt": "L3-001851", "subCtNm": "FLOOR CLEANING", "ct": "L4-000449", "ctNm": "HOME ELECTRICS", "seg": "L5-000054", "segNm": "HARD HOME", "area": "L6-000012", "areaNm": "IN AND OUTDOOR HOME" }, { "cls": "L2-006796", "clsNm": "VACUUMS STICK", "subCt": "L3-001851", "subCtNm": "FLOOR CLEANING", "ct": "L4-000449", "ctNm": "HOME ELECTRICS", "seg": "L5-000054", "segNm": "HARD HOME", "area": "L6-000012", "areaNm": "IN AND OUTDOOR HOME" }, { "cls": "L2-012895", "clsNm": "FLOOR STEAM MOPS", "subCt": "L3-001851", "subCtNm": "FLOOR CLEANING", "ct": "L4-000449", "ctNm": "HOME ELECTRICS", "seg": "L5-000054", "segNm": "HARD HOME", "area": "L6-000012", "areaNm": "IN AND OUTDOOR HOME" }] ; $scope.loadMP6DataToMemory = function(data) { angular.forEach(data, function (value, key) { if ($.inArray(value.area, $scope.mp6Root) === -1) { $scope.mp6Root.push(value.area); } addToMap(value.cls, value.clsNm, ""); addToMap(value.subCt, value.subCtNm, value.cls); addToMap(value.ct, value.ctNm, value.subCt); addToMap(value.seg, value.segNm, value.ct); addToMap(value.area, value.areaNm, value.seg); }); } addToMap = function (pKey, pName, pChild) { if (!$scope.mp6Data[pKey]) { cSet = []; $scope.mp6Data[pKey] = { name: pName, children: cSet }; } else { if ($.inArray(pChild, $scope.mp6Data[pKey].children) === -1) { $scope.mp6Data[pKey].children.push(pChild); } } } $scope.ExpandMP6 = function (pKey) { if (pKey) { mp = $scope.mp6Data[pKey]; return { name: mp.name, children: mp.children, visible: false } } } $scope.loadMP6DataToMemory(data); $scope.l5visible = false; $scope.l4visible = false; $scope.l3visible = false; $scope.l2visible = false; }); 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <div class="container" ng-app="HelloWorldApp" ng-controller="HelloWorldController"> <div class="md-grid"> <ul class="md-list"> <li class="md-list-item-text" ng:repeat="l6 in mp6Root" ng-click="l5visible = !l5visible; $event.stopPropagation();"> L6 {{ExpandMP6(l6).name}} <ul class="md-list" ng-show="l5visible"> <li class="md-list-item-text" ng:repeat="l5 in ExpandMP6(l6).children" ng-click="l4visible = !l4visible; $event.stopPropagation();"> L5 {{ExpandMP6(l5).name}} <ul class="md-list" ng-show="l4visible"> <li class="md-list-item-text" ng:repeat="l4 in ExpandMP6(l5).children" ng-click="l3visible = !l3visible; $event.stopPropagation();"> L4 {{ExpandMP6(l4).name}} <ul class="md-list" ng-show="l3visible"> <li class="md-list-item-text" ng:repeat="l3 in ExpandMP6(l4).children" ng-click="l2visible = !l2visible; $event.stopPropagation();"> L3 {{ExpandMP6(l3).name}} <ul class="md-list" ng-show="l2visible"> <li class="md-list-item-text" ng:repeat="l2 in ExpandMP6(l3).children"> L2 {{ExpandMP6(l2).name}} </li> </ul> </li> </ul> </li> </ul> </li> </ul> </li> </ul> </div> </div> 

編輯:這是我想到的過濾器,但似乎不適應我構建html的方式: 如何從angularjs中的文本框中過濾數據

如果需要更改HTML結構,我願意接受建議。

首先,您應該創建一個嵌套指令來顯示您的樹。 如果突然顯示7個級別怎么辦? 所以首先我要寫一個遞歸指令,這也會減少代碼大小。

對於數據過濾部分,可以使用一個input與一個ng-model-options="{debounce: 300}"聯合ng-change="filterFunction()" ,以便濾波只適用300ms的用戶已經完成寫入其之后搜索。 一旦您的數據以分層形式構建, filterFunction()很容易編寫,並且可以更改對象狀態以指示您的指令是否應該顯示,並且應該顯示其子項。

結果如下:

MainController.js

var app = angular.module('app', []);
app.controller('MainController', [function () {
  var ctrl = this;
  ctrl.search = '';
  initHierarchies(); // function that transforms the data in hierarchical form
  // filterHierarchies is called everytime the user changed the search input
  ctrl.filterHierarchies = function () {
    ctrl.filteredHierarchies = hierarchiesFilter(ctrl.hierarchies, ctrl.search).hierarchies;
  }
  ctrl.filterHierarchies(); // init the filteredHierarchies data.

  // function that filters the hierarchy. It is a recursive function
  function hierarchiesFilter(hierarchies, search) {
    if (!hierarchies || !hierarchies.length) {
      return { hierarchies: [], hasExpandedChildren: false};
    }
    console.log(hierarchies, search);
    var oneIsExpanded = false;
    for (var i = 0; i < hierarchies.length; i++) {
      hierarchies[i].showChildren = false;
      if (search.length) {
        var rx = new RegExp(search, 'i');
        if (hierarchies[i].name.match(rx)) {
          oneIsExpanded = true;
        }
      }
      // if the node has children which are expanded, we need to display it so its children that
      // should be highlighted are visible
      var hasExpandedChildren = hierarchiesFilter(hierarchies[i].children, search).hasExpandedChildren;
      if (hasExpandedChildren) {
        hierarchies[i].showChildren = true;
        oneIsExpanded = true;
      }
    }
    return { hierarchies: hierarchies, hasExpandedChildren: oneIsExpanded };
  };

  // function to transform the array data to a hierarchical structure
  function initHierarchies() {
    var data = getData();
    var mp6Data = {};
    var mp6Root = [];

    angular.forEach(data, function (value, key) {
        if (mp6Root.indexOf(value.area) === -1) {
            mp6Root.push(value.area);
        }

        addToMap(value.cls, value.clsNm, "");
        addToMap(value.subCt, value.subCtNm, value.cls);
        addToMap(value.ct, value.ctNm, value.subCt);
        addToMap(value.seg, value.segNm, value.ct);
        addToMap(value.area, value.areaNm, value.seg);
    });

    function addToMap(pKey, pName, pChild) {
        if (!mp6Data[pKey]) {
            mp6Data[pKey] = { name: pName, childrenKeys: [] };
        } else {
            if (mp6Data[pKey].childrenKeys.indexOf(pChild) === -1) {
                mp6Data[pKey].childrenKeys.push(pChild);
            }
        }
    }

    function buildHierarchicalStructure(childrenKeys) {
      var builtChildren = [];
      for (var i = 0; i < childrenKeys.length; i++) {
        builtChildren.push({
          name: mp6Data[childrenKeys[i]].name,
          children: buildHierarchicalStructure(mp6Data[childrenKeys[i]].childrenKeys)
        });
      }
      return builtChildren;
    }

    for (var i = 0; i < mp6Data.length; i++) {
      mp6Data[i].showChildren = true;
    }
    ctrl.hierarchies = buildHierarchicalStructure(mp6Root);
  }
}]);

hierarchy.directive.js

app.directive('hierarchy', ['RecursionHelper', function (RecursionHelper) {
  return {
    template: '<div><div ng-click="hierarchyCtrl.ngModel.showChildren = !hierarchyCtrl.ngModel.showChildren">{{ hierarchyCtrl.ngModel.name }}</div><ul ng-if="hierarchyCtrl.ngModel.children && (hierarchyCtrl.ngModel.showChildren)"><li ng-repeat="element in hierarchyCtrl.ngModel.children"><hierarchy ng-model="element"></hierarchy></li></ul></div>',
    restrict: 'E',
    scope: { ngModel: '=' },
    controller: ['$scope', function($scope) { this.ngModel = $scope.ngModel; }],
    controllerAs: 'hierarchyCtrl',
    compile: function (element) { 
      return RecursionHelper.compile(element);
    },
  };
}]);

的index.html

<body>
<h1>Hello Plunker!</h1>
<div ng-controller="MainController as mainCtrl">
  <input type="text" ng-model="mainCtrl.search" ng-model-options="{debounce: 300}" ng-change="mainCtrl.filterHierarchies()" />
  <ul>
    <li ng-repeat="hierarchy in mainCtrl.filteredHierarchies"><hierarchy ng-model="hierarchy"></hierarchy></li>
  </ul>
</div>
</body>

Plunker示例: https ://plnkr.co/edit/1jiiiwkdUZY4tm7sm79F p = preview

我會讓你編寫代碼部分來突出顯示與搜索匹配的文本,因為它很容易轉換進行過濾的函數。 提示:在hierarchiesFilter()函數中,您可以將htmlHighlighted屬性添加到每個節點,在這些節點中包裝<strong></strong>標記之間的匹配文本。

由於這可能不是您正在尋找的確切行為,您可以調整過濾器功能,以便在用戶更改搜索時准確顯示您想要的內容。

一些代碼(遞歸助手)來自這篇文章: Angular指令中的遞歸

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM