ufollettu
ufollettu

Reputation: 882

Angular 5 - using filter in select tag with pipe

I have a select html tag and I want to filter my list of results by the selected value. I'm using a pipe to show them in a *ngFor created list. when I add a new item, the select tag add a new option, even if there's an option with the same name yet. How could I fix this? I want my select tag to show unique value only (Filter???). I'd like to set a default value too.

Screenshot:

enter image description here

App.component.html:

<div class="container">
  <div class="row">
  <div class="col-xs-12 col-sm-10 col-md-8 col-sm-offset-1 col-md-offset-2">

  <select
    name="serverStatus"
    id="serverStatus"
    [(ngModel)]="filteredStatus">
    <option
      *ngFor="let server of servers"
      value="{{server.status}}">{{server.status}}</option>
  </select>
  <hr>
  <ul class="list-group">
    <li
      class="list-group-item"
      *ngFor="let server of servers | filter:filteredStatus:'status'"
      [ngClass]="getStatusClasses(server)">
      <span
        class="badge">
        {{ server.status }}
      </span>
      <strong>{{ server.name }}</strong> |
      {{ server.instanceType | uppercase }} |
      {{ server.started | date:'fullDate' | uppercase }}
    </li>
  </ul>
</div>

App.component.ts:

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  servers = [
{
  instanceType: 'medium',
  name: 'Production Server',
  status: 'stable',
  started: new Date(15, 1, 2017)
},
{
  instanceType: 'large',
  name: 'User Database',
  status: 'stable',
  started: new Date(15, 1, 2017)
},
{
  instanceType: 'small',
  name: 'Development Server',
  status: 'offline',
  started: new Date(15, 1, 2017)
},
{
  instanceType: 'small',
  name: 'Testing Environment Server',
  status: 'critical',
  started: new Date(15, 1, 2017)
}
];

filteredStatus = '';

getStatusClasses(server: {instanceType: string, name: string, status: string, started: Date}) {
return {
  'list-group-item-success': server.status === 'stable',
  'list-group-item-warning': server.status === 'offline',
  'list-group-item-danger': server.status === 'critical'
};
}
}

fiter.pipe.ts:

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'filter'
})
export class FilterPipe implements PipeTransform {

transform(value: string[], filterString: string, propName:string): any {
if (value.length === 0 || filterString === '') {
  return value;
}
const resultArray = [];
for (const item of value) {
  if (item[propName] === filterString) {
    resultArray.push(item)
  }
}
return resultArray;
}
}

Here is a stackblitz working example: https://angular-rwmfbj.stackblitz.io Editor: https://stackblitz.com/edit/angular-nck1kn

Upvotes: 1

Views: 3561

Answers (2)

Eljah
Eljah

Reputation: 5165

It was difficult to believe, but my code based on this example didn't work until I have explicitly added the "name" filed with some value in the input text field. Nothing occured during the filtering

Upvotes: 0

John Velasquez
John Velasquez

Reputation: 3451

Try this

App.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  servers = [
    {
      instanceType: 'medium',
      name: 'Production Server',
      status: 'stable',
      started: new Date(15, 1, 2017)
    },
    {
      instanceType: 'large',
      name: 'User Database',
      status: 'stable',
      started: new Date(15, 1, 2017)
    },
    {
      instanceType: 'small',
      name: 'Development Server',
      status: 'offline',
      started: new Date(15, 1, 2017)
    },
    {
      instanceType: 'small',
      name: 'Testing Environment Server',
      status: 'critical',
      started: new Date(15, 1, 2017)
    }
  ];

  filteredStatus = '';

  serverStatus:  {
      instanceType: string,
      name: string,
      status: string,
      started: Date
    }[] = [];

    constructor(){
      this.initializeStatus();

     //For setting the default value of the select try this
     if(this.serverStatus.length != 0)
        this.filteredStatus = this.serverStatus[0].status;
    }

  getStatusClasses(server: {instanceType: string, name: string, status: string, started: Date}) {
    return {
      'list-group-item-success': server.status === 'stable',
      'list-group-item-warning': server.status === 'offline',
      'list-group-item-danger': server.status === 'critical'
    };
  }

  //Initalize the status
  initializeStatus(){
    this.serverStatus = [];
    //Container for the current status
    let currentStatus = "";
      for(let x of this.servers){
        if(x.status != currentStatus){
          this.serverStatus.push(x);
        }
        //Equate for reference
        currentStatus = x.status;
      }
  }
}

In App.component.html

change *ngFor="let server of servers" to this *ngFor="let server of serverStatus"

Upvotes: 1

Related Questions