2015-09-15 3 views
1

Я хотел бы создать фильтр на вложенных объектов, например:AngularJS Фильтр по вложенным свойствам

Object 1 : 
property1 
property2 
property3 
children : Child 1 : 
      propertyChild1 
      propertyChild2 
      Child 2 : 

И так далее. Объект может иметь несколько дочерних элементов. Там нет предела глубины specified.The проблема заключается в том, что я хочу, чтобы искать только на определенных свойствах объекта, так я использовал:

ng-repeat="groupLevel1 in groupLevel2.children | filter: {lineDescription: searchKeyword}" 

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

Я попробовал некоторые сложные сценарии, но он не работает:

appReportingHoliday.filter('globalFilter', function(){ 
return function(array, predicate){ 
    return array.filter(function(val){ 
     var formattedObj = parseFloatInternational(predicate); 
     var re = new RegExp(formattedObj, 'i'); 
     var initialArray = []; 
     initialArray.push(val); 
     var childIsNeeded = false; 
     var toReturnTemp; 
     var parents = []; 
     var toReturn = []; 
     while(initialArray!=null){ 
      angular.forEach(initialArray, function (currentVal) { 
       toReturnTemp = false; 
       //We check if the val is concerned by the search 
       toReturnTemp = re.test(currentVal.lineDescription) || re.test(currentVal.acquiredHolidays) || re.test(currentVal.tokenHolidays) || re.test(currentVal.availableHolidays) 
         || re.test(currentVal.dailyCost) || re.test(currentVal.valuation); 

       if (toReturnTemp) { 
        //if it is, we need to add the result to the toReturn array and also the parents that we could have saved in the according array 
        toReturn.push(currentVal); 
        toReturn.push(parents); 
        parents = []; 
       } 
       else { 
        //else we save it in the parents array if a child is needed 
        if(currentVal.children!=null) { 
         parents.push(currentVal); 
        } 
       } 
       var index = initialArray.indexOf(currentVal); 
       initialArray.splice(index, 1); 
       if(currentVal.children!=null) { 
        angular.forEach(currentVal.children, function (currentChild) { 
         initialArray.push(currentChild); 
        }); 

       } 
      }); 
      if(initialArray.length==0) initialArray = null; 
     } 
     return toReturn; 
    }); 
} 
}); 

Дисплей выполнен так:

<tr class="groupReportingTreeDatatable" ng-repeat-start="groupLevel3 in myData | filter: {lineDescription: searchKeyword}" ng-init="$index &lt; 2 ? groupLevel3.hideRows = false : groupLevel3.hideRows = true;" ng-class-even="'dataTable_row1'" ng-class-odd="'dataTable_row2'" spinner-handler-directive=""> 
         ... 
<tr class="groupReportingTreeDatatable" ng-hide="groupLevel3.hideRows" ng-init="groupLevel2.hideRows = true" ng-repeat-start="groupLevel2 in groupLevel3.children | filter: {lineDescription: searchKeyword}" ng-class-even="'dataTable_row1'" ng-class-odd="'dataTable_row2'"> 

         ... 


<tr ng-hide="groupLevel2.hideRows || groupLevel3.hideRows" ng-repeat="groupLevel1 in groupLevel2.children | filter: {lineDescription: searchKeyword}" ng-class-even="'dataTable_row1'" ng-class-odd="'dataTable_row2'" ng-repeat-end=""> 

EDIT: Я пытался что-то еще, который работает для некоторых поисков, но не все из них: (

appReportingHoliday.filter('globalFilter', function() { 
return function (array, predicate) { 
    return array.filter(function (val) { 
     var formattedObj = parseFloatInternational(predicate); 
     var re = new RegExp(formattedObj, 'i'); 
     var found = re.test(val.lineDescription) || re.test(val.acquiredHolidays) || re.test(val.tokenHolidays) || re.test(val.availableHolidays) 
         || re.test(val.dailyCost) || re.test(val.valuation); 
     var child = val.children; 

     while(child!=null && found == false){ 
      angular.forEach(child, function (currentChild) { 
       if(found == false) { 
        console.log(currentChild.lineDescription) 
        found = re.test(currentChild.lineDescription) || re.test(currentChild.acquiredHolidays) || re.test(currentChild.tokenHolidays) || re.test(currentChild.availableHolidays) 
          || re.test(currentChild.dailyCost) || re.test(currentChild.valuation); 
       } 
      }); 
      child = child.children; 
     } 

     return found; 
    }); 
} 
}); 

ответ

0

Не было бы проще иметь вторая переменная, где вы сглаживаете всех детей первого? Вы можете определить рекурсивную функцию, что-то вроде ...

var mainObject = ... ;//that's your object 
var flattened = new Array(); 

function flatten(main,flat) { 
    var children = main.children; 
    for (var i=0;i<children.length;i++) { 
     flatten(children[i],flat); // recursive call, depth-first 
     delete children[i].children; // those are already treated 
     flat.push(children[i]); // add children 
    } 
    delete main.children; 
    flat.push(main); 
} 

Теперь вы можете напрямую фильтровать свойства.

+0

У меня действительно плохо с рекурсивными методами, я попробовал один, но он не был включен. Не фильтрует ли фильтр на var, который фактически отображается на странице? Потому что я не вижу, как я могу использовать th e second var, если он фактически не используется на экране. Я добавил новый код ниже, так как не смог написать весь код в разделе комментариев – user3314017

0

Я не вижу, как интегрировать это в свой код. Я не могу изменить базовую переменную, потому что мне нужна она в этой структуре, чтобы отображать ее на экране. Я могу создать еще один сплющенный массив, но фильтр должен быть применен к отображению var I, нет? Поэтому я не могу использовать сплющенный var. Я должен признать, что я немного потерял ^^

Я установил глубину до 3, чтобы сделать его проще, так что теперь у меня есть это:

appReportingHoliday.filter('globalFilter', function() { 
return function (array, predicate) { 
    return array.filter(function (val) { 
     var formattedObj = parseFloatInternational(predicate); 
     var re = new RegExp(formattedObj, 'i'); 
     var found = re.test(val.lineDescription) || re.test(val.acquiredHolidays) || re.test(val.tokenHolidays) || re.test(val.availableHolidays) 
         || re.test(val.dailyCost) || re.test(val.valuation); 
     var child = val.children; 

     if(child!=null && found == false){ 
      angular.forEach(child, function (currentChild) { 
       if(found == false) { 
        found = re.test(currentChild.lineDescription) || re.test(currentChild.acquiredHolidays) || re.test(currentChild.tokenHolidays) || re.test(currentChild.availableHolidays) 
          || re.test(currentChild.dailyCost) || re.test(currentChild.valuation); 
       } 
       if(currentChild.children!=null && found == false){ 
        angular.forEach(currentChild.children, function (currentGrandChild) { 
         if(found == false) { 
          found = re.test(currentGrandChild.lineDescription) || re.test(currentGrandChild.acquiredHolidays) || re.test(currentGrandChild.tokenHolidays) || re.test(currentGrandChild.availableHolidays) 
            || re.test(currentGrandChild.dailyCost) || re.test(currentGrandChild.valuation); 
         } 
        }); 
       } 

      }); 
      child = child.children; 
     } 
     return found; 
    }); 
    } 
}); 

Единственная проблема, которая остается в том, что если поиск на родительском я хочу, чтобы все дочерние элементы отображались, но сейчас отображаются только соответствующие дочерние элементы: s Я не могу найти родителя от ребенка, у меня есть только ссылка от родителя к ребенку, а не наоборот: s

Смежные вопросы