Monday 16 July 2018

How to filter complex structured Json data in Angular 6

I have a complex structured json data that needs to be apply an advanced filtering in my Angular 6 App.

JSON Data:

[{
    "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"
        }
    ]
 }]

Filter Options:

I would like to have 3 drop-down list in HTML page to filter by:
  1. Sex
  2. ProgramCategory
  3. ProgramStatus

HTML View:

The UI View will look like the below: enter image description here

Wanted Result:

When I select ProgramCategory = 'HR' and ProgramStatus = 'Part Time', there will be only 2 students (student1,student2) returned. I spend days try to get the result that I want, but still not solve. I use this article as ref and made some improvement based on my data, but the returned data is incorrect, see the image below: enter image description here So, I only need the marked rows (row#:1,2) to be returned.
The the marked row#:5 is marked by mistake in the image above.

My ts 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 => i === value;
    this.setFilters();
  }

  filterMatchSub(property: string, childProperty: string, value: any) {
    this.filters[property] = val => val.find( child => 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"
              }
          ]
       }
  ]
    `);
  }

}

My HTML Code:

<div class="row">

    <div class="col-sm-12">
        <div class="panel panel-sm ">
            <div class="panel-body">
                <h5>Basic Info</h5>
                <div class="hs-lead">
                    <div class="row">
                        <div class="col-sm-3">
                            <div class="form-group">
                                <label for="exampleSelect1">Sex</label>
                                <div class="row">
                                    <div class="col-sm-9">
                                        <select class="form-control" [(ngModel)]="Sex"
 (change)="filterMatch('Sex', Sex)">
                                            <option value="M">M</option>
                                            <option value="F">F</option>
                                        </select>
                                    </div>
                                    <div class="col-sm-3">
                                        <button class="btn btn-primary" *ngIf="Sex"
 (click)="removeFilter('Sex')">
                                            Clear
                                        </button>
                                    </div>
                                </div>
                            </div>
                        </div>
                        <div class="col-sm-3">
                            <div class="form-group">
                                <label for="exampleSelect1">ProgramCategory</label>
                                <div class="row">
                                    <div class="col-sm-9">
                                        <select class="form-control"
 [(ngModel)]="ProgramCategory"
 (change)="filterMatchSub('Programs', 'ProgramCategory', ProgramCategory)">
                                            <option value="Engineering">Engineering</option>
                                            <option value="HR">HR</option>
                                            <option value="Finance">Finance</option>
                                        </select>
                                    </div>
                                    <div class="col-sm-3">
                                        <button class="btn btn-primary" 
*ngIf="ProgramCategory" (click)="removeFilter('Programs')">
                                                Clear
                                        </button>
                                    </div>
                                </div>
                            </div>
                        </div>

                        <div class="col-sm-3">
                            <div class="form-group">
                                <label for="exampleSelect1">ProgramStatus</label>
                                <div class="row">
                                    <div class="col-sm-9">
                                        <select class="form-control" [(ngModel)]="ProgramStatus" 
(change)="filterMatchSub('Programs', 'ProgramStatus', ProgramStatus)">
                                            <option value="Full Time">Full Time</option>
                                            <option value="Part Time">Part Time</option>
                                        </select>
                                    </div>
                                    <div class="col-sm-3">
                                        <button class="btn btn-primary" *ngIf="ProgramStatus"
(click)="removeFilter('Programs')">
                                                Clear
                                        </button>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>

                </div>
            </div>
        </div>

    </div>



</div>

<div class="row">
    <div class="col-sm-12">
        <div class="panel panel-xl">
            <div class="panel-body">
                <h5>Result
                    <span class="badge badge-info badge-pill pull-right"></span>
                </h5>
                <div class="hs-lead">
                    <div class="table-responsive">
                        <table class="table table-hover">
                            <thead>
                                <tr>
                                    <th>#</th>
                                    <th>Name</th>
                                    <th>Sex</th>
                                    <th>Programs</th>
                                </tr>
                            </thead>
                            <tbody>
                                <tr *ngFor="let item of filteredStudents ">
                                    <td></td>
                                    <td></td>
                                    <td></td>
                                    <td>
                                        

                                        <ol *ngFor="let obj of item.Programs">
                                            <li> / </li>
                                        </ol>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                    </div>

                </div>
            </div>
        </div>
    </div>
</div>

Help:

Could anyone help me to achieve my goal?
You can change my current ts code or have a new solution, both are welcomed!
Thanks a lot!


from How to filter complex structured Json data in Angular 6

No comments:

Post a Comment