Search code examples
javascriptangularjsangular-ng-if

Angular ng-if any child contains


I'm trying to conditionally show and hide columns based on the data returned, if the data set contains any objects meeting conditions.

Here is a sample of the data returned from my search results

[
    {
        "id": "typeahead-241-1091-option-0",
        "label": "Android Home Page",
        "model": {
            "type": "link",
        }
    },
    {
        "id": "typeahead-241-1091-option-1",
        "label": "Google",
        "model": {
            "type": "link",

        }
    },
    {
        "id": "typeahead-241-1091-option-2",
        "label": "Forgotten Google Play Password",
        "model": {
            "type": "kb",

        }
    }
]

Now I'm presenting the data in columns, based on the type.

<div class="flexitem">
  <h4>External Links</h4>
  <div ng-repeat="match in matches" ng-if="match.model.type == 'link'">{{match.label}}</div>
</div>
<div class="flexitem">
  <h4>Knowledge Base</h4>
  <div ng-repeat="match in matches" ng-if="match.model.type == 'kb'">{{match.label}}</div>
</div>
<!-- the below has no results. I want it hidden altogether
currently it shows the <h4>Products</h4> with nothing below it-->
<div class="flexitem">
  <h4>Products</h4>
  <div ng-repeat="match in matches" ng-if="match.model.type == 'product'">{{match.label}}</div>
</div>

What I need to accomplish is putting conditions on the flexitem divs altogether to only show if there are results for that type. So if there are no results with the type == 'product', then don't even show that div. A ng-if on that row would work, but what will be the best way to cycle through all of the children of match to determine if there is a result? indexOf doesn't work through children arrays.


Solution

  • Put the logic on the angular side using Array.filter to separate arrays;

    Angular controller:

    $scope.linkMathches = $scope.matches.filter(function(m){
      return m.model.type === 'link'
    });
    $scope.kbMathches = $scope.matches.filter(function(m){
      return m.model.type === 'kb'
    });
    

    HTML:

    <div class="flexitem" ng-if="linkMathches.length">
      <h4>External Links</h4>
      <div ng-repeat="match in linkMathches">
        {{match.label}}
      </div>
    </div>
    <div class="flexitem" ng-if="kbMathches.length">
      <h4>Knowledge Base</h4>
      <div ng-repeat="match in kbMathches">
        {{match.label}}
      </div>
    </div>
    

    Going further for dynamic values in model.type:

    Angular controller:

    $scope.typeMatches = {
      link: {title: 'External Links', matches: []},
      kb: {title: 'Knowledge Base', matches: []},
      product: {title: 'Products', matches: []}
    };
    
    $scope.matches.forEach(function(match){
      $scope.typeMatches[match.model.type].matches.push(match);
    });
    

    HTML:

    <div class="flexitem"
        ng-if="value.matches.length"
        ng-repeat="(key,value) in typeMatches">
      <h4>{{value.title}}</h4>
      <div ng-repeat="match in value.matches">
        {{match.label}}
      </div>
    </div>