Do I always have to declare a variable in angular2 to get changes?

151 views Asked by At

I have the following code:

This is the HTML view:

<button type="button" (click)="filterIt('male')">Filter male gender</button>
     <table>
       <ng-container *ngFor="let item of array;let i=index">
       <tr class="border-bottom" *ngIf="item.condition==condition_var">
         <td>{{i+1}}</td>
         <td>{{item.condition}}</td>
       </tr>
     </ng-container>
</table>

This is the typescript file (.ts):

  condition_var:string;
   filterIt(value){
     this.condition_var=value;
  }

NOTE: the array variable is already populated. (array of objects: [{}])

My question is: Is it a practice in angular2 to always declare variables and to work with them in expressions, ngIf, ngFor etc. Or can I use a better way rather than populating my class with too many variables which doesn't look good.

To be more specific, is there a better way to write this code?

5

There are 5 answers

3
msanford On BEST ANSWER

Yes there is a better (more idiomatic) way to do this: use a @Pipe.

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

@Pipe({ name: 'filter' })
export class FilterPipe implements PipeTransform {
  transform(values: any, condition: any): any {
    return values.filter(item => item.condition === condition);
  }
}

Implement with:

<ng-container *ngFor="let item of array | filter:condition">

And set the condition however you like. Note that filters can accept more than one positional parameter, separated by colons.

Remember to add the pipe to whichever @NgModules you use the pipe in:

import { FilterPipe } from 'pipes/fitler.pipe.ts';

@NgModule({
  declaractions: [
    FilterPipe
  ],
  // ...
})

And if the @NgModule in question is a lazy-loaded "shared" module, don't forget to re-export it:

@NgModule({
      declaractions: [
        FilterPipe
      ],
      exports: [
        FilterPipe
      ],
      // ...
    })

This answer is currently valid as of angular 4.3.6.

0
cyr_x On

I would use a getter inside your component class which filters the array you're looping over. Like this:

public myArray: any[] = [];
public myCondition: string | null = null;

public get myFilteredArray() {
  return this.myArray.filter(item => item.condition === this.myCondition);
}

And in your template just use the filteredArray:

<table>
  <tr class="border-bottom" *ngFor="let item of myFilteredArray;let i=index">
    <td>{{i+1}}</td>
    <td>{{item.condition}}</td>
  </tr>
</table>

Or you could build a pipe for it:

@Pipe({ name: 'myFilterPipe' })
export class MyFilterPipe implements PipeTransform {
  transform(value: any[], condition: string | null): any[] {
    if(!Array.isArray(value)) return [];
    return value.filter(item => item.condition === condition);
  }
}
0
FAISAL On

Here is an approach if you want to avoid declaring the variable in your class. Just initialize variable on button click:

<button type="button" (click)="condition = 'male'">Filter male gender</button>
<table>
    <ng-container *ngFor="let item of array;let i=index">
        <tr class="border-bottom" *ngIf="item.condition == condition">
            <td>{{i+1}}</td>
            <td>{{item.condition}}</td>
        </tr>
    </ng-container>
</table>

You don't have to declare condition, condition_var or filterIt() method in your class in this way. Link to Plunker Demo.

1
Kunvar Singh On

In your case, you are filtering the data based on "male" string.

So you can directly use the following snippets:

*ngIf="item.condition=='male'"

don't need to make function, it will handle in if block,

0
sander On

I would solve it this way:

//YOUR COMPONENT .TS CODE
filterIt(parameter: String){
//filter this.array here using your parameter
}

//YOUR COMPONENT .HTML CODE
<button type="button" (click)="filterIt('male')">Filter male gender</button>
 <table>
   <ng-container *ngFor="let item of array;">
   <tr class="border-bottom">
     <td>{{i+1}}</td>
     <td>{{item.condition}}</td>
   </tr>
 </ng-container>

This is much cleaner and let's the logic happen in your.ts file while your web page only displays.