title: How to filter complex structured Json data in Angular 6
body: <p>I have a complex structured json data that needs to be apply an advanced filtering in my Angular 6 App. </p>
  
  <h3>JSON Data:</h3>
  
  <pre><code>[{
      "StudentId": 1,
      "StudentName": "Student1",
      "Sex":"M",
      "Programs": [
          {
              "StudentId": 1,
              "ProgramName": "Java",
              "ProgramCategory": "Engineering",
              "ProgramStatus": "Full Time"
          },
          {
              "StudentId": 1,
              "ProgramName": "HR Management 2",
              "ProgramCategory": "HR",
              "ProgramStatus": "Part Time"
          },
          {
              "StudentId": 1,
              "ProgramName": "Accounting 1",
              "ProgramCategory": "Finance",
              "ProgramStatus": "Full Time"
          }
      ]
   },
  {
      "StudentId": 2,
      "StudentName": "Student2",
      "Sex":"F",
      "Programs": [
          {
              "StudentId": 2,
              "ProgramName": "HR Management 1",
              "ProgramCategory": "HR",
              "ProgramStatus": "Part Time"
          },
          {
              "StudentId": 2,
              "ProgramName": "Accounting 3",
              "ProgramCategory": "Finance",
              "ProgramStatus": "Full Time"
          }
      ]
   },
  {
      "StudentId": 3,
      "StudentName": "Student3",
      "Sex":"F",
      "Programs": [
          {
              "StudentId": 3,
              "ProgramName": "Java 3",
              "ProgramCategory": "Engineering",
              "ProgramStatus": "Full Time"
          }
      ]
   },
  {
      "StudentId": 4,
      "StudentName": "Student4",
      "Sex":"M",
      "Programs": [
          {
              "StudentId": 4,
              "ProgramName": "Java 2",
              "ProgramCategory": "Engineering",
              "ProgramStatus": "Full Time"
          },
          {
              "StudentId": 4,
              "ProgramName": "Accounting 2",
              "ProgramCategory": "Finance",
              "ProgramStatus": "Part Time"
          }
      ]
   },
   {
      "StudentId": 5,
      "StudentName": "Student5",
      "Sex":"M",
      "Programs": [
          {
              "StudentId": 5,
              "ProgramName": "JavaScript",
              "ProgramCategory": "Engineering",
              "ProgramStatus": "Part Time"
          },
          {
              "StudentId": 5,
              "ProgramName": "HR Management 5",
              "ProgramCategory": "HR",
              "ProgramStatus": "Full Time"
          }
      ]
   }]
  </code></pre>
  
  <h3>Filter Options:</h3>
  
  <p>I would like to have 3 drop-down list in HTML page to filter by:</p>
  
  <ol>
  <li>Sex</li>
  <li>ProgramCategory</li>
  <li>ProgramStatus</li>
  </ol>
  
  <h3>HTML View:</h3>
  
  <p>The UI View will look like the below:
  <a href="https://i.stack.imgur.com/aTIiM.png" rel="noreferrer"><img src="https://i.stack.imgur.com/aTIiM.png" alt="enter image description here"></a></p>
  
  <h3>Wanted Result:</h3>
  
  <p>When I select <code>ProgramCategory = 'HR'</code> and <code>ProgramStatus = 'Part Time'</code>, there will be only 2 students (<code>student1</code>,<code>student2</code>) returned. I spend days try to get the result that I want, but still not solve. I use this <a href="https://angularfirebase.com/lessons/multi-property-data-filtering-with-firebase-and-angular-4/" rel="noreferrer">article</a> as ref and made some improvement based on my data, but the returned data is incorrect, see the image below:
    <a href="https://i.stack.imgur.com/cYRWp.png" rel="noreferrer"><img src="https://i.stack.imgur.com/cYRWp.png" alt="enter image description here"></a>
  So, I only need the marked rows (<code>row#:1,2</code>) to be returned.</p>
  
  <p>The the marked <strong>row#:5 is marked by mistake</strong> in the image above.</p>
  
  <h3>My ts code:</h3>
  
  <pre><code>import { Component, OnInit } from '@angular/core';
  import * as _ from 'lodash';
  
  @Component({
    selector: 'app-hfo',
    templateUrl: './hfo.component.html',
    styleUrls: ['./hfo.component.css']
  })
  export class HfoComponent implements OnInit {
  
    students: any;
    filteredStudents: any;
  
    // basic info
    Sex: string;
    // child info
    ProgramCategory: string;
    ProgramStatus: string;
  
    // filter by value
    filters = { };
  
    constructor() { }
  
    ngOnInit() {
      /// get all students
      this.students = this.getStudents();
      this.setFilters();
    }
  
    private setFilters() {
      this.filteredStudents = _.filter(this.students, _.conforms(this.filters) );
    }
  
    filterMatch(property: string, value: any) {
      this.filters[property] = i =&gt; i === value;
      this.setFilters();
    }
  
    filterMatchSub(property: string, childProperty: string, value: any) {
      this.filters[property] = val =&gt; val.find( child =&gt; child[childProperty]  === value);
      this.setFilters();
    }
  
    /// removes filter
    removeFilter(property: string) {
      delete this.filters[property];
      this[property] = null;
      this.ProgramCategory = null;
      this.ProgramStatus = null;
      this.setFilters();
    }
  
    private getStudents() {
      return JSON.parse(`
      [
        {
            "StudentId": 1,
            "StudentName": "Student1",
            "Sex":"M",
            "Programs": [
                {
                    "StudentId": 1,
                    "ProgramName": "Java",
                    "ProgramCategory": "Engineering",
                    "ProgramStatus": "Full Time"
                },
                {
                    "StudentId": 1,
                    "ProgramName": "HR Management 2",
                    "ProgramCategory": "HR",
                    "ProgramStatus": "Part Time"
                },
                {
                    "StudentId": 1,
                    "ProgramName": "Accounting 1",
                    "ProgramCategory": "Finance",
                    "ProgramStatus": "Full Time"
                }
            ]
         },
        {
            "StudentId": 2,
            "StudentName": "Student2",
            "Sex":"F",
            "Programs": [
                {
                    "StudentId": 2,
                    "ProgramName": "HR Management 1",
                    "ProgramCategory": "HR",
                    "ProgramStatus": "Part Time"
                },
                {
                    "StudentId": 2,
                    "ProgramName": "Accounting 3",
                    "ProgramCategory": "Finance",
                    "ProgramStatus": "Full Time"
                }
            ]
         },
        {
            "StudentId": 3,
            "StudentName": "Student3",
            "Sex":"F",
            "Programs": [
                {
                    "StudentId": 3,
                    "ProgramName": "Java 3",
                    "ProgramCategory": "Engineering",
                    "ProgramStatus": "Full Time"
                }
            ]
         },
        {
            "StudentId": 4,
            "StudentName": "Student4",
            "Sex":"M",
            "Programs": [
                {
                    "StudentId": 4,
                    "ProgramName": "Java 2",
                    "ProgramCategory": "Engineering",
                    "ProgramStatus": "Full Time"
                },
                {
                    "StudentId": 4,
                    "ProgramName": "Accounting 2",
                    "ProgramCategory": "Finance",
                    "ProgramStatus": "Part Time"
                }
            ]
         },
         {
            "StudentId": 5,
            "StudentName": "Student5",
            "Sex":"M",
            "Programs": [
                {
                    "StudentId": 5,
                    "ProgramName": "JavaScript",
                    "ProgramCategory": "Engineering",
                    "ProgramStatus": "Part Time"
                },
                {
                    "StudentId": 5,
                    "ProgramName": "HR Management 5",
                    "ProgramCategory": "HR",
                    "ProgramStatus": "Full Time"
                }
            ]
         }
    ]
      `);
    }
  
  }
  </code></pre>
  
  <h3>My HTML Code:</h3>
  
  <pre><code>&lt;div class="row"&gt;
  
      &lt;div class="col-sm-12"&gt;
          &lt;div class="panel panel-sm "&gt;
              &lt;div class="panel-body"&gt;
                  &lt;h5&gt;Basic Info&lt;/h5&gt;
                  &lt;div class="hs-lead"&gt;
                      &lt;div class="row"&gt;
                          &lt;div class="col-sm-3"&gt;
                              &lt;div class="form-group"&gt;
                                  &lt;label for="exampleSelect1"&gt;Sex&lt;/label&gt;
                                  &lt;div class="row"&gt;
                                      &lt;div class="col-sm-9"&gt;
                                          &lt;select class="form-control" [(ngModel)]="Sex" (change)="filterMatch('Sex', Sex)"&gt;
                                              &lt;option value="M"&gt;M&lt;/option&gt;
                                              &lt;option value="F"&gt;F&lt;/option&gt;
                                          &lt;/select&gt;
                                      &lt;/div&gt;
                                      &lt;div class="col-sm-3"&gt;
                                          &lt;button class="btn btn-primary" *ngIf="Sex" (click)="removeFilter('Sex')"&gt;
                                              Clear
                                          &lt;/button&gt;
                                      &lt;/div&gt;
                                  &lt;/div&gt;
                              &lt;/div&gt;
                          &lt;/div&gt;
                          &lt;div class="col-sm-3"&gt;
                              &lt;div class="form-group"&gt;
                                  &lt;label for="exampleSelect1"&gt;ProgramCategory&lt;/label&gt;
                                  &lt;div class="row"&gt;
                                      &lt;div class="col-sm-9"&gt;
                                          &lt;select class="form-control" [(ngModel)]="ProgramCategory" (change)="filterMatchSub('Programs', 'ProgramCategory', ProgramCategory)"&gt;
                                              &lt;option value="Engineering"&gt;Engineering&lt;/option&gt;
                                              &lt;option value="HR"&gt;HR&lt;/option&gt;
                                              &lt;option value="Finance"&gt;Finance&lt;/option&gt;
                                          &lt;/select&gt;
                                      &lt;/div&gt;
                                      &lt;div class="col-sm-3"&gt;
                                          &lt;button class="btn btn-primary" *ngIf="ProgramCategory" (click)="removeFilter('Programs')"&gt;
                                                  Clear
                                          &lt;/button&gt;
                                      &lt;/div&gt;
                                  &lt;/div&gt;
                              &lt;/div&gt;
                          &lt;/div&gt;
  
                          &lt;div class="col-sm-3"&gt;
                              &lt;div class="form-group"&gt;
                                  &lt;label for="exampleSelect1"&gt;ProgramStatus&lt;/label&gt;
                                  &lt;div class="row"&gt;
                                      &lt;div class="col-sm-9"&gt;
                                          &lt;select class="form-control" [(ngModel)]="ProgramStatus" (change)="filterMatchSub('Programs', 'ProgramStatus', ProgramStatus)"&gt;
                                              &lt;option value="Full Time"&gt;Full Time&lt;/option&gt;
                                              &lt;option value="Part Time"&gt;Part Time&lt;/option&gt;
                                          &lt;/select&gt;
                                      &lt;/div&gt;
                                      &lt;div class="col-sm-3"&gt;
                                          &lt;button class="btn btn-primary" *ngIf="ProgramStatus" (click)="removeFilter('Programs')"&gt;
                                                  Clear
                                          &lt;/button&gt;
                                      &lt;/div&gt;
                                  &lt;/div&gt;
                              &lt;/div&gt;
                          &lt;/div&gt;
                      &lt;/div&gt;
  
                  &lt;/div&gt;
              &lt;/div&gt;
          &lt;/div&gt;
  
      &lt;/div&gt;
  
  
  
  &lt;/div&gt;
  
  &lt;div class="row"&gt;
      &lt;div class="col-sm-12"&gt;
          &lt;div class="panel panel-xl"&gt;
              &lt;div class="panel-body"&gt;
                  &lt;h5&gt;Result
                      &lt;span class="badge badge-info badge-pill pull-right"&gt;{{ filteredStudents.length }}&lt;/span&gt;
                  &lt;/h5&gt;
                  &lt;div class="hs-lead"&gt;
                      &lt;div class="table-responsive"&gt;
                          &lt;table class="table table-hover"&gt;
                              &lt;thead&gt;
                                  &lt;tr&gt;
                                      &lt;th&gt;#&lt;/th&gt;
                                      &lt;th&gt;Name&lt;/th&gt;
                                      &lt;th&gt;Sex&lt;/th&gt;
                                      &lt;th&gt;Programs&lt;/th&gt;
                                  &lt;/tr&gt;
                              &lt;/thead&gt;
                              &lt;tbody&gt;
                                  &lt;tr *ngFor="let item of filteredStudents "&gt;
                                      &lt;td&gt;{{item.StudentId }}&lt;/td&gt;
                                      &lt;td&gt;{{item.StudentName }}&lt;/td&gt;
                                      &lt;td&gt;{{item.Sex}}&lt;/td&gt;
                                      &lt;td&gt;
                                          {{item.Programs.length}}
  
                                          &lt;ol *ngFor="let obj of item.Programs"&gt;
                                              &lt;li&gt;{{obj.ProgramCategory}} / {{obj.ProgramStatus}}&lt;/li&gt;
                                          &lt;/ol&gt;
                                      &lt;/td&gt;
                                  &lt;/tr&gt;
                              &lt;/tbody&gt;
                          &lt;/table&gt;
                      &lt;/div&gt;
  
                  &lt;/div&gt;
              &lt;/div&gt;
          &lt;/div&gt;
      &lt;/div&gt;
  &lt;/div&gt;
  </code></pre>
  
  <h3>Help:</h3>
  
  <p>Could anyone help me to achieve my goal?</p>
  
  <p>You can change my current ts code or have a new solution, both are welcomed!</p>
  
  <p>Thanks a lot! </p>