이번 실습에서는 Angular 앱에 검색 기능을 추가하는 방법을 알아봅니다.
사용자는 앱에서 제공하는 데이터를 검색할 수 있으며, 앱에는 입력한 검색어에 맞는 결과만 표시됩니다.
IMPORTANT: 이 실습은 로컬 환경에서 진행하는 것을 권장합니다.
학습 목표
- 폼의 입력값으로 조건에 맞는 주택을 검색합니다.
- 검색 조건에 맞는 주택만 표시합니다.
-
Home 컴포넌트의 프로퍼티 수정하기
이 단계에서는 필터링에 사용할 새 배열 프로퍼티를
Home클래스에 추가합니다.src/app/home/home.ts의 클래스에filteredLocationList프로퍼티를 추가하세요.home.ts에 filteredLocationList 프로퍼티 추가하기
import {ChangeDetectorRef, Component, inject} from '@angular/core'; import {HousingLocation} from '../housing-location/housing-location'; import {HousingLocationInfo} from '../housinglocation'; import {HousingService} from '../housing.service'; @Component({ selector: 'app-home', imports: [HousingLocation], template: ` <section> <form> <input type="text" placeholder="Filter by city" #filter /> <button class="primary" type="button" (click)="filterResults(filter.value)">Search</button> </form> </section> <section class="results"> @for (housingLocation of filteredLocationList; track $index) { <app-housing-location [housingLocation]="housingLocation" /> } </section> `, styleUrls: ['./home.css'], }) export class Home { private readonly changeDetectorRef = inject(ChangeDetectorRef); housingLocationList: HousingLocationInfo[] = []; housingService: HousingService = inject(HousingService); filteredLocationList: HousingLocationInfo[] = []; constructor() { this.housingLocationList = this.housingService.getAllHousingLocations(); this.filteredLocationList = this.housingLocationList; } filterResults(text: string) { if (!text) { this.filteredLocationList = this.housingLocationList; return; } this.filteredLocationList = this.housingLocationList.filter((housingLocation) => housingLocation?.city.toLowerCase().includes(text.toLowerCase()), ); } }filteredLocationList에는 사용자가 입력한 검색 조건에 맞는 값이 저장됩니다.페이지를 처음 불러왔을 때는
filteredLocationList에 전체 주택 목록이 있어야 합니다.Home의constructor에서 이 값을 설정하세요.filteredLocationList 값 설정하기
import {ChangeDetectorRef, Component, inject} from '@angular/core'; import {HousingLocation} from '../housing-location/housing-location'; import {HousingLocationInfo} from '../housinglocation'; import {HousingService} from '../housing.service'; @Component({ selector: 'app-home', imports: [HousingLocation], template: ` <section> <form> <input type="text" placeholder="Filter by city" #filter /> <button class="primary" type="button" (click)="filterResults(filter.value)">Search</button> </form> </section> <section class="results"> @for (housingLocation of filteredLocationList; track $index) { <app-housing-location [housingLocation]="housingLocation" /> } </section> `, styleUrls: ['./home.css'], }) export class Home { private readonly changeDetectorRef = inject(ChangeDetectorRef); housingLocationList: HousingLocationInfo[] = []; housingService: HousingService = inject(HousingService); filteredLocationList: HousingLocationInfo[] = []; constructor() { this.housingLocationList = this.housingService.getAllHousingLocations(); this.filteredLocationList = this.housingLocationList; } filterResults(text: string) { if (!text) { this.filteredLocationList = this.housingLocationList; return; } this.filteredLocationList = this.housingLocationList.filter((housingLocation) => housingLocation?.city.toLowerCase().includes(text.toLowerCase()), ); } }
-
Home 컴포넌트의 템플릿 수정하기
Home에는 사용자 입력을 받을 필드가 이미 있습니다. 여기에 입력한 문자열로 결과를 필터링합니다.Home템플릿의input엘리먼트에#filter템플릿 변수를 추가하세요.home.ts의 input HTML 엘리먼트에 템플릿 변수 추가하기
import {ChangeDetectorRef, Component, inject} from '@angular/core'; import {HousingLocation} from '../housing-location/housing-location'; import {HousingLocationInfo} from '../housinglocation'; import {HousingService} from '../housing.service'; @Component({ selector: 'app-home', imports: [HousingLocation], template: ` <section> <form> <input type="text" placeholder="Filter by city" #filter /> <button class="primary" type="button" (click)="filterResults(filter.value)">Search</button> </form> </section> <section class="results"> @for (housingLocation of filteredLocationList; track $index) { <app-housing-location [housingLocation]="housingLocation" /> } </section> `, styleUrls: ['./home.css'], }) export class Home { private readonly changeDetectorRef = inject(ChangeDetectorRef); housingLocationList: HousingLocationInfo[] = []; housingService: HousingService = inject(HousingService); filteredLocationList: HousingLocationInfo[] = []; constructor() { this.housingLocationList = this.housingService.getAllHousingLocations(); this.filteredLocationList = this.housingLocationList; } filterResults(text: string) { if (!text) { this.filteredLocationList = this.housingLocationList; return; } this.filteredLocationList = this.housingLocationList.filter((housingLocation) => housingLocation?.city.toLowerCase().includes(text.toLowerCase()), ); } }이 예제는 템플릿 참조 변수를 사용해
input엘리먼트에 접근합니다.다음으로 컴포넌트 템플릿의 "Search" 버튼에 이벤트 핸들러를 연결하세요.
home.ts에서 버튼 클릭 이벤트를 메서드에 바인딩하기
import {ChangeDetectorRef, Component, inject} from '@angular/core'; import {HousingLocation} from '../housing-location/housing-location'; import {HousingLocationInfo} from '../housinglocation'; import {HousingService} from '../housing.service'; @Component({ selector: 'app-home', imports: [HousingLocation], template: ` <section> <form> <input type="text" placeholder="Filter by city" #filter /> <button class="primary" type="button" (click)="filterResults(filter.value)">Search</button> </form> </section> <section class="results"> @for (housingLocation of filteredLocationList; track $index) { <app-housing-location [housingLocation]="housingLocation" /> } </section> `, styleUrls: ['./home.css'], }) export class Home { private readonly changeDetectorRef = inject(ChangeDetectorRef); housingLocationList: HousingLocationInfo[] = []; housingService: HousingService = inject(HousingService); filteredLocationList: HousingLocationInfo[] = []; constructor() { this.housingLocationList = this.housingService.getAllHousingLocations(); this.filteredLocationList = this.housingLocationList; } filterResults(text: string) { if (!text) { this.filteredLocationList = this.housingLocationList; return; } this.filteredLocationList = this.housingLocationList.filter((housingLocation) => housingLocation?.city.toLowerCase().includes(text.toLowerCase()), ); } }button엘리먼트의click이벤트를 바인딩하면filterResults함수를 호출할 수 있습니다. 함수에는filter템플릿 변수의value프로퍼티, 즉inputHTML 엘리먼트의.value를 인자로 전달합니다.마지막으로
@for블록이filteredLocationList배열의 값을 순회하도록 수정하세요.home.ts의 @for 템플릿 블록 수정하기
import {ChangeDetectorRef, Component, inject} from '@angular/core'; import {HousingLocation} from '../housing-location/housing-location'; import {HousingLocationInfo} from '../housinglocation'; import {HousingService} from '../housing.service'; @Component({ selector: 'app-home', imports: [HousingLocation], template: ` <section> <form> <input type="text" placeholder="Filter by city" #filter /> <button class="primary" type="button" (click)="filterResults(filter.value)">Search</button> </form> </section> <section class="results"> @for (housingLocation of filteredLocationList; track $index) { <app-housing-location [housingLocation]="housingLocation" /> } </section> `, styleUrls: ['./home.css'], }) export class Home { private readonly changeDetectorRef = inject(ChangeDetectorRef); housingLocationList: HousingLocationInfo[] = []; housingService: HousingService = inject(HousingService); filteredLocationList: HousingLocationInfo[] = []; constructor() { this.housingLocationList = this.housingService.getAllHousingLocations(); this.filteredLocationList = this.housingLocationList; } filterResults(text: string) { if (!text) { this.filteredLocationList = this.housingLocationList; return; } this.filteredLocationList = this.housingLocationList.filter((housingLocation) => housingLocation?.city.toLowerCase().includes(text.toLowerCase()), ); } }
-
이벤트 핸들러 함수 구현하기
템플릿의
click이벤트에filterResults함수를 바인딩했습니다. 이제Home클래스에filterResults함수를 구현합니다.Home클래스에filterResults함수 구현을 추가하세요.filterResults 함수 구현 추가하기
import {ChangeDetectorRef, Component, inject} from '@angular/core'; import {HousingLocation} from '../housing-location/housing-location'; import {HousingLocationInfo} from '../housinglocation'; import {HousingService} from '../housing.service'; @Component({ selector: 'app-home', imports: [HousingLocation], template: ` <section> <form> <input type="text" placeholder="Filter by city" #filter /> <button class="primary" type="button" (click)="filterResults(filter.value)">Search</button> </form> </section> <section class="results"> @for (housingLocation of filteredLocationList; track $index) { <app-housing-location [housingLocation]="housingLocation" /> } </section> `, styleUrls: ['./home.css'], }) export class Home { private readonly changeDetectorRef = inject(ChangeDetectorRef); housingLocationList: HousingLocationInfo[] = []; housingService: HousingService = inject(HousingService); filteredLocationList: HousingLocationInfo[] = []; constructor() { this.housingLocationList = this.housingService.getAllHousingLocations(); this.filteredLocationList = this.housingLocationList; } filterResults(text: string) { if (!text) { this.filteredLocationList = this.housingLocationList; return; } this.filteredLocationList = this.housingLocationList.filter((housingLocation) => housingLocation?.city.toLowerCase().includes(text.toLowerCase()), ); } }이 함수는
Array의filter메서드로text파라미터와housingLocation.city프로퍼티를 비교합니다. 추가 연습으로 다른 프로퍼티나 여러 프로퍼티를 비교하도록 수정해 보세요.코드를 저장하세요.
브라우저를 새로고침하고 텍스트를 입력한 뒤 "Search" 버튼을 클릭했을 때 도시 이름으로 주택 정보를 검색할 수 있는지 확인하세요.

SUMMARY: 이번 실습에서는 템플릿 변수로 템플릿의 값에 접근하고, 이벤트 바인딩과 배열 메서드로 검색 기능을 추가했습니다.
이 실습에서 다룬 내용을 더 알아보려면 다음 문서를 참고하세요: