2

I have followed the Angular 2 tour of Heroes tutorial, and I am currently at this stage:

https://angular.io/docs/ts/latest/tutorial/toh-pt6.html

I can search in the search bar, and a list of hero name suggestions come up

Plunker: https://angular.io/resources/live-examples/toh-6/ts/eplnkr.html

However, what I want, is a filter bar, where I search, and the hero block automatically gets filtered depending on what is in the filter bar.

For example, in the link I provided, if I type in "Bo" in the search bar, I only want the hero block "Bombasto" to show up on the screen. When I clear the search bar, all the blocks should reappear. Does someone know how to do this?

Seeker
  • 262
  • 1
  • 5
  • 17
  • 1
    Maybe you could create a minimal plunker? – slaesh Dec 22 '16 at 12:15
  • Theres a plunker in the link I provided (towards the bottom). – Seeker Dec 22 '16 at 12:18
  • I should really have added it to the post. Here you go https://angular.io/resources/live-examples/toh-6/ts/eplnkr.html – Seeker Dec 22 '16 at 12:19
  • this might help you: http://stackoverflow.com/a/34165371/5115768 basically you create a `custom pipe` which filters your `heroes` array based on the search string (in the answer called `filterargs`) – lenny Dec 22 '16 at 12:22
  • So you want the hero's displayed in the dashboard component to change based on what's in the search box? – Peza Dec 22 '16 at 12:23
  • @Peza Yes, exactly. – Seeker Dec 22 '16 at 12:24

1 Answers1

3

Take a look at my modified plunker: https://plnkr.co/edit/YHzyzm6ZXt4ESr76mNuB?p=preview

  1. Added a Pipe to the dashboard.component.ts
@Pipe({
  name: 'filterHeros'
})
export class FilterHeroPipe {
  public transform(heros: Hero[], filter: string) {
    if (!heros || !heros.length) return [];
    if (!filter) return heros;
    return heros.filter(h => h.name.toLowerCase().indexOf(filter.toLowerCase()) >= 0);
  }
}
  1. Use this Pipe inside of that dashboard.template
<h3>Top Heroes</h3>
<div class="grid grid-pad">
  <a *ngFor="let hero of (heroes | filterHeros : heroSearch.curSearch )"  [routerLink]="['/detail', hero.id]"  class="col-1-4">
    <div class="module hero">
      <h4>{{hero.name}}</h4>
    </div>
  </a>
</div>
<br />
<hero-search #heroSearch></hero-search>
  1. Change that HeroSearch component:
  private searchTerms = new Subject<string>();
  public curSearch: string; // !! NEW !!

  constructor(
    private heroSearchService: HeroSearchService,
    private router: Router) {}

  // Push a search term into the observable stream.
  search(term: string): void {
    this.curSearch = term;  // !! NEW !!
    this.searchTerms.next(term);
  }
  1. don't forget to add our Pipe to our app.module:
import { DashboardComponent, FilterHeroPipe }   from './dashboard.component';
import { HeroesComponent }      from './heroes.component';
import { HeroDetailComponent }  from './hero-detail.component';
import { HeroService }          from './hero.service';
import { HeroSearchComponent }  from './hero-search.component';

@NgModule({
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule,
    InMemoryWebApiModule.forRoot(InMemoryDataService),
    AppRoutingModule
  ],
  declarations: [
    AppComponent,
    DashboardComponent,
    HeroDetailComponent,
    HeroesComponent,
    HeroSearchComponent,
    FilterHeroPipe
  ],
  providers: [ HeroService ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }
slaesh
  • 16,659
  • 6
  • 50
  • 52