Angular 소개

1. 소개

빌드할 항목

이 Codelab에서는 Angular를 사용하여 주택 앱을 빌드합니다. 완성된 앱에서는 사용자 검색을 기반으로 집 등록정보를 보고 주택 위치의 세부정보를 볼 수 있습니다.

Angular의 강력한 도구와 훌륭한 브라우저 통합을 사용하여 Angular로 모든 것을 빌드하게 됩니다.

오늘 빌드할 앱입니다.

학습할 내용

  • Angular CLI를 사용하여 새 프로젝트를 지원하는 방법
  • Angular 구성요소를 사용하여 사용자 인터페이스를 빌드하는 방법
  • 앱의 구성요소 및 기타 부분에서 데이터를 공유하는 방법
  • Angular에서 이벤트 핸들러를 사용하는 방법
  • Angular CLI를 사용하여 Firebase 호스팅에 앱을 배포하는 방법

필요한 항목

  • HTML, CSS, TypeScript (또는 자바스크립트), Git, 명령줄에 관한 기본 지식

2. 환경 설정

로컬 환경 설정

이 Codelab을 완료하려면 로컬 머신에 다음 소프트웨어가 설치되어 있어야 합니다.

Angular CLI 설치

모든 종속 항목이 구성되면 컴퓨터의 명령줄 창에서 Angular CLI를 설치할 수 있습니다.

npm install -g @angular/cli

구성이 올바른지 확인하려면 컴퓨터의 명령줄에서 다음 명령어를 실행하세요.

ng –version

명령어가 정상적으로 작동하면 아래 스크린샷과 비슷한 메시지가 표시됩니다.

Angular 버전을 표시하는 Angular CLI 출력

코드 가져오기

이 Codelab의 코드에는 중간 단계와 최종 분기가 여러 분기에 포함되어 있습니다. 시작하려면 GitHub에서 코드를 다운로드하세요.

  1. 새 브라우저 탭을 열고 https://github.com/angular/introduction-to-angular로 이동합니다.
  2. 명령줄 창에서 포크하여 저장소와 cd introduction-to-angular/를 저장소에 클론합니다.
  3. 시작 코드 브랜치에서 git checkout get-started를 입력합니다.
  4. 원하는 코드 편집기에서 코드를 열고 introduction-to-angular 프로젝트 폴더를 엽니다.
  5. 명령줄 창에서 npm install을 실행하여 서버를 실행하는 데 필요한 종속 항목을 설치합니다.
  6. 백그라운드에서 Angular 웹 서버를 실행하려면 별도의 명령줄 창을 열고 ng serve를 실행하여 서버를 시작합니다.
  7. http://localhost:4200에서 브라우저 탭을 엽니다.

앱이 실행되면 페어하우스 앱 빌드를 시작할 수 있습니다.

3. 첫 번째 구성요소 만들기

구성요소는 Angular 앱의 핵심 구성요소입니다. 구성요소는 건설에 사용되는 벽돌이라고 생각하면 됩니다. 시작할 때 벽돌은 힘이 많지만, 다른 벽돌과 결합하면 멋진 구조를 만들 수 있습니다.

Angular로 빌드된 앱의 경우에도 마찬가지입니다.

구성요소의 주요 내용은 다음 세 가지입니다.

  • 템플릿의 HTML 파일입니다.
  • 스타일의 CSS 파일입니다.
  • 앱 동작의 TypeScript 파일

첫 번째로 업데이트할 구성요소는 AppComponent입니다.

  1. 코드 편집기에서 app.component.html을 엽니다. AppComponent의 템플릿 파일입니다.
  2. 이 파일의 코드를 모두 삭제하고 다음으로 바꿉니다.
<main>
  <header><img src="../assets/logo.svg" alt="fairhouse">Fairhouse</header>
  <section>
  </section>
</main>
  1. 코드를 저장하고 브라우저를 확인합니다. 개발 서버를 실행하면 변경사항을 저장하면 변경사항이 브라우저에 반영됩니다.

축하합니다. 첫 Angular 앱을 업데이트했습니다. 더 많은 기능을 기대해 주세요. 계속하겠습니다.

다음으로, 검색을 위한 텍스트 필드와 UI를 버튼에 추가합니다.

구성요소는 UI를 구성할 수 있는 기능을 제공한다는 등 여러 이점이 있습니다. 텍스트 필드, 검색 버튼, 최종적으로 위치 목록이 포함된 구성요소를 만들 것입니다.

이 새로운 구성요소를 생성하려면 Angular CLI를 사용해야 합니다. Angular CLI는 Scaffolding, 배포 등을 지원하는 명령줄 도구 모음입니다.

  1. 명령줄에서 다음을 입력합니다.
ng generate component housing-list

다음은 이 명령어의 일부입니다.

  • ng는 Angular CLI입니다.
  • 이 명령어는 실행할 작업 유형을 생성합니다. 이 경우 무언가에 대한 스캐폴딩을 생성하세요.
  • 구성요소에서는 만들고자 하는 내용을 나타냅니다.
  • building-list는 구성요소의 이름입니다.
  1. 다음으로 새 구성요소를 AppComponent 템플릿에 추가합니다. app.component.html에서 템플릿 코드를 업데이트합니다.
<main>
  <header><img src="../assets/logo.svg" alt="fairhouse">Fairhouse</header>
 <section>
   <app-housing-list></app-housing-list>
 </section>
</main>
  1. 모든 파일을 저장하고 브라우저로 돌아가서 housing-list works 메시지가 표시되는지 확인합니다.
  2. 코드 편집기에서 housing-list.component.html로 이동하여 기존 코드를 삭제하고 다음으로 바꿉니다.
<label for="location-search">Search for a new place</label>
<input id="location-search" placeholder="Ex: Chicago"><button>Search</button>
  1. housing-list.component.css에서 다음 스타일을 추가합니다.
input, button {
    border: solid 1px #555B6E;
    border-radius: 2px;
    display: inline-block;
    padding: 0;
}
input {
    width: 400px;
    height: 40px;
    border-radius: 2px 0 0 2px;
    color: #888c9c;
    border: solid 1px #888c9c;
    padding: 0 5px 0 10px;
}

button {
    width: 70px;
    height: 42px;
    background-color: #4468e8;
    color: white;
    border: solid 1px #4468e8;
    border-radius: 0 2px 2px 0;
}

article {
    margin: 40px 0 10px 0;
    color: #202845;
}
article, article > p {
    color: #202845;
}

article> p:first-of-type {
    font-weight: bold;
    font-size: 22pt;
}

img {
    width: 490px;
    border-radius: 5pt;
}

label {
    display: block;
    color: #888c9c;
}

  1. 파일을 저장한 다음 브라우저로 돌아갑니다. 이제 앱에 검색창과 버튼이 있음

Angular 앱이 모습을 갖추기 시작했습니다.

4. 이벤트 처리

앱에는 입력란과 버튼이 있지만 상호작용이 없습니다. 웹에서 일반적으로 컨트롤과 상호작용하고 이벤트 및 이벤트 핸들러의 사용을 호출합니다. 이 전략을 사용하여 앱을 빌드합니다.

housing-list.component.html에서 변경합니다.

클릭 핸들러를 추가하려면 버튼에 이벤트 리스너를 추가해야 합니다. Angular에서 구문은 이벤트 이름을 괄호로 묶고 값을 할당하는 것입니다. 여기서는 버튼을 클릭할 때 호출되는 메서드의 이름을 지정합니다. 그 이름을 searchHousingLocations라고 하겠습니다. 이 함수 이름 끝에 괄호를 추가하여 호출해야 합니다.

  1. 다음 코드와 일치하도록 버튼 코드를 업데이트합니다.
<button (click)="searchHousingLocations()">Search</button>
  1. 코드를 저장하고 브라우저를 확인하세요. 이제 컴파일 오류가 발생합니다.

46a528b5ddbc7ef8.png

앱에서 이 오류가 발생합니다. searchHousingLocations 메서드가 없기 때문에 변경해야 합니다.

  1. housing-list.component.ts에서 HousingListComponent 클래스의 본문 끝에 새 메서드를 추가합니다.
 searchHousingLocations() {}

이 방법에 대한 세부정보를 곧 작성하겠습니다.

  1. 이 코드를 저장하여 브라우저를 업데이트하고 오류를 해결합니다.

다음 단계는 입력란의 값을 가져와서 searchHousingLocations 메서드에 인수로 전달하는 것입니다. 템플릿 변수라는 Angular 기능을 사용합니다. 이 기능을 통해 템플릿의 요소를 참조하는 방식 및 상호작용이 가능합니다.

  1. housing-list.component.html에서 입력에 해시태그로 해시태그가 있는 search라는 속성을 추가합니다.
<label for="location-search">Search for a new place</label>
<input id="location-search" #search><button (click)="searchHousingLocations()">Search</button>

이제 입력에 대한 참조가 있습니다. 입력의 .value 속성에도 액세스할 수 있습니다.

  1. 입력 값을 searchHousingLocations 메서드에 전달합니다.
<input id="location-search" #search><button (click)="searchHousingLocations(search.value)">Search</button>

지금까지는 값을 매개변수로 전달했지만, 이 메서드를 사용하여 메서드를 업데이트하면 됩니다. 현재 이 매개변수는 console.log 명령어에서 사용되며, 나중에는 검색 매개변수로 사용됩니다.

  1. housing-list.component.ts에서 다음 코드를 추가합니다.
 searchHousingLocations(searchText: string) {
   console.log(searchText);
 }
  1. 코드를 저장한 다음 브라우저에서 Chrome DevTools를 열고 Console 탭으로 이동합니다. 입력에 값을 입력합니다. Search를 선택하고 Chrome DevTools의 콘솔 탭에 값이 표시되는지 확인합니다.

UI의 검색 텍스트와 일치하는 Chrome devtools 콘솔 출력

이벤트 핸들러를 성공적으로 추가했으며 앱에서 사용자의 입력을 수신할 수 있습니다.

5. 검색결과

다음 단계는 사용자 입력을 기반으로 결과를 표시하는 것입니다. 각 위치에는 이름, 도시, 주, 사진의 문자열 속성, availableUnits의 숫자 속성, 세탁과 Wi-Fi의 부울 속성 두 개가 있습니다.

name: "Location One",
city: "Chicago",
state: "IL",
photo: "/path/to/photo.jpg",
availableUnits: 4,
wifi: true,
laundry: true

이 데이터를 일반 자바스크립트 객체로 표시할 수 있지만, Angular에서 TypeScript 지원을 사용하는 것이 더 좋습니다. 유형을 사용하여 빌드 중 오류를 방지할 수 있습니다.

유형을 사용하여 데이터 특성을 정의할 수 있으며, 이를 '데이터 셰이핑'이라고 합니다. TypeScript에서는 인터페이스가 일반적으로 이 용도로 사용됩니다. 주택 위치 데이터를 나타내는 인터페이스를 만들어 보겠습니다. 편집기 터미널에서 Angular CLI를 사용하여 HousingLocation 유형을 만듭니다.

  1. 다음과 같이 입력하세요.
ng generate interface housing-location
  1. housing-location.ts에서 인터페이스의 유형 세부정보를 추가합니다. 디자인에 따라 각 속성에 적절한 유형을 지정합니다.
export interface HousingLocation {
  name: string,
  city: string,
  state: string,
  photo: string,
  availableUnits: number,
  wifi: boolean,
  laundry: boolean,
}
  1. 파일을 저장하고 app.component.ts을 엽니다.
  2. ./housing-location에서 주택 위치 인터페이스를 가져와 주택 위치를 나타내는 데이터가 포함된 배열을 만들려면
import { HousingLocation } from './housing-location';
  1. HousingLocation[] 유형의 housingLocationList라는 속성을 포함하도록 AppComponent 클래스를 업데이트합니다. 다음 값으로 배열을 채웁니다.
housingLocationList: HousingLocation[] = [
  {
    name: "Acme Fresh Start Housing",
    city: "Chicago",
    state: "IL",
    photo: "../assets/housing-1.jpg",
    availableUnits: 4,
    wifi: true,
    laundry: true,
  },
  {
    name: "A113 Transitional Housing",
    city: "Santa Monica",
    state: "CA",
    photo: "../assets/housing-2.jpg",
    availableUnits: 0,
    wifi: false,
    laundry: true,
  },
  {
    name: "Warm Beds Housing Support",
    city: "Juneau",
    state: "AK",
    photo: "../assets/housing-3.jpg",
    availableUnits: 1,
    wifi: false,
    laundry: false,
  }
];

객체를 가져오기 위해 클래스의 새 인스턴스를 인스턴스화할 필요가 없습니다. 인터페이스에서 제공하는 유형 정보를 활용할 수 있습니다. 객체의 데이터는 동일한 'shape'여야 합니다. 즉, 인터페이스에 정의된 속성과 일치해야 합니다.

데이터는 app.component.ts에 저장되지만, 이를 다른 구성요소와 공유해야 합니다. 한 가지 해결책은 Angular의 서비스를 사용하는 것이지만 앱의 복잡성을 줄이기 위해 Angular에서 제공하는 입력 데코레이터를 사용하게 됩니다. 입력 데코레이터는 구성요소가 템플릿에서 값을 수신하도록 해 줍니다. 이 함수를 사용하여 housingLocationList 배열을 HousingListComponent와 공유합니다.

  1. housing-list.component.ts에서 @angular/coreinput./housingLocationHousingLocation를 가져옵니다.
import { Component, OnInit, Input } from '@angular/core';
import {HousingLocation } from '../housing-location';
  1. 구성요소 클래스의 본문에 locationList라는 속성을 만듭니다. Input님을 locationList의 데코레이터로 사용하려고 합니다.
export class HousingListComponent implements OnInit {

  @Input() locationList: HousingLocation[] = [];
  ...
}

이 속성의 유형은 HousingLocation[]로 설정됩니다.

  1. app.component.html에서 locationList라는 속성을 포함하도록 app-housing-list 요소를 업데이트하고 값을 housingLocationList로 설정합니다.
<main>
 ...
 <app-housing-list [locationList]="housingLocationList"></app-housing-list>
</main>

locationList 속성이 대괄호([ ])로 묶여 있어야 Angular에서 locationList 속성의 값을 동적으로 값 또는 변수나 표현식에 바인딩할 수 있습니다. 그렇지 않으면 Angular는 등호의 오른쪽에 있는 값을 문자열로 취급합니다.

이 시점에서 오류가 발생하면 다음을 확인하세요.

  • 입력 속성 이름의 철자는 TypeScript 클래스의 속성에 있는 맞춤법과 일치합니다. 케이스도 여기에 중요합니다.
  • 등호 오른쪽에 있는 속성 이름의 철자가 정확합니다.
  • 입력 속성은 대괄호로 묶여 있습니다.

데이터 공유 구성이 완료되었습니다. 다음 단계는 브라우저에 결과를 표시하는 것입니다. 데이터가 배열 형식이므로 데이터를 반복하고 템플릿 *ngFor의 요소를 반복할 수 있는 Angular 기능을 사용해야 합니다.

  1. housing-list.component.html에서 브라우저에 배열 항목을 표시할 수 있도록 템플릿의 기사 요소를 업데이트하여 *ngFor를 사용합니다.
<article *ngFor="let location of locationList"></article>

ngFor 속성에 할당된 값은 Angular 템플릿 구문입니다. 템플릿에서 로컬 변수를 만듭니다. Angular는 공개 및 종료 태그 사이의 article 요소 범위에서 로컬 변수를 사용합니다.

ngFor템플릿 구문에 대한 자세한 내용은 Angular 문서를 참조하세요.

ngForlocationList 배열의 항목마다 기사 요소를 반복합니다. 다음으로, 위치 변수의 값을 표시합니다.

  1. 단락 요소(<p>) 요소를 추가하도록 템플릿을 업데이트합니다. 단락 요소의 하위 요소는 위치 속성에서 보간된 값입니다.
<input #search><button (click)="searchHousingLocations(search.value)">Search</button>
<article *ngFor="let location of locationList">
   <p>{{location.name}}</p>
</article>

Angular 템플릿에서 텍스트 보간 유형을 사용하여 이중 중괄호 ( {{ }}) 구문으로 값을 표시할 수 있습니다.

  1. 저장하고 브라우저로 돌아갑니다. 이제 앱이 locationList 배열의 각 배열 항목에 하나의 라벨을 표시합니다.

주택 위치 3곳으로 나열된 등록정보

데이터는 앱 구성요소에서 주택 목록 구성요소로 공유되며, 각 값을 반복하여 브라우저에 표시합니다.

지금까지 구성요소 간에 데이터를 공유하는 몇 가지 방법을 다루었으며 몇 가지 새로운 템플릿 구문과 ngFor 명령어를 사용했습니다.

6. 검색결과 필터링

현재 앱이 사용자의 검색을 기반으로 한 결과 대신 모든 결과를 표시합니다. 이를 변경하려면 앱이 의도한 대로 작동할 수 있도록 HousingListComponent를 업데이트해야 합니다.

  1. housing-list.component.ts에서 HousingLocation[] 유형인 results라는 새 속성을 갖도록 HousingListComponent를 업데이트합니다.
export class HousingListComponent implements OnInit {

 @Input() locationList: HousingLocation[] = [];
 results: HousingLocation[] = [];
 ...

결과 배열은 사용자 검색과 일치하는 주택 위치를 나타냅니다. 다음 단계는 searchHousingLocations 메서드를 업데이트하여 값을 필터링하는 것입니다.

  1. console.log를 삭제하고 searchText를 필터링하여 locationList를 필터링하는 출력에 결과 속성을 할당하는 코드를 업데이트합니다.
searchHousingLocations(searchText: string) {
  this.results = this.locationList.filter(
  (location: HousingLocation) => location.city
    .toLowerCase()
    .includes(
        searchText.toLowerCase()
  ));
}

이 코드에서 배열 필터 메서드를 사용하고 searchText가 포함된 값만 허용합니다. 모든 값은 소문자로 표기된 문자열을 사용하여 비교됩니다.

두 가지 유의사항:

  • 메서드 내에서 클래스의 속성을 참조할 때 this 접두사를 사용해야 합니다. 이러한 이유로 this.resultsthis.locationList를 사용하고 있습니다.
  • 여기서 검색 기능은 위치의 도시 속성과만 일치하지만 코드를 업데이트하여 더 많은 속성을 포함할 수 있습니다.

이 코드는 그대로 작동하지만 개선할 수 있습니다.

  1. 다음 코드를 검색하여 searchText 비어 있는 경우 배열을 검색하지 못하게 하는 코드를 업데이트합니다.
searchHousingLocations(searchText: string) {
  if (!searchText) return;
  ...
}

메서드가 업데이트되었으며 브라우저에 결과를 표시하기 전에 변경해야 하는 템플릿 변경이 있습니다.

  1. housing-location.component.html에서 ngForlocationListresults로 바꿉니다.
<article *ngFor="let location of results">...</article>
  1. 코드를 저장하고 브라우저로 돌아갑니다. 입력을 사용하여 샘플 데이터의 위치 (예: 시카고)를 검색합니다.

앱에는 일치하는 결과만 표시됩니다.

검색창에 입력한 텍스트와 일치하는 검색결과

사용자 입력을 검색결과에 완전히 연결하는 데 필요한 추가 기능을 완료했습니다. 앱이 거의 완성되었습니다.

다음으로, 앱에 관한 세부정보를 표시하여 완료합니다.

7. 세부정보 표시

앱이 검색결과를 클릭하고 세부정보 패널에 정보를 표시하도록 지원해야 합니다. HousingListComponent는 구성요소가 구성요소에 표시된 이후 클릭된 결과를 알고 있습니다. HousingListComponent의 데이터를 상위 구성요소 AppComponent와 공유하는 방법이 필요합니다.

Angular에서 @Input()는 상위 요소에서 하위 요소로 데이터를 전송하는 반면, @Output()는 구성요소가 상위 요소에서 하위 구성요소로 데이터를 전송하는 이벤트를 보낼 수 있도록 합니다. 출력 데코레이터는 EventEmitter를 사용하여 모든 이벤트에서 리스너에게 알립니다. 이 경우 검색결과 클릭을 나타내는 이벤트를 내보내려고 합니다. 선택 이벤트와 함께 선택한 항목을 페이로드의 일부로 전송하려고 합니다.

  1. housing-list.component.ts에서 import를 업데이트하여 위치에서 @angular/coreHousingLocationOutputEventEmitter를 포함합니다.
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { HousingLocation } from '../housing-location';
  1. HousingListComponent의 본문에서 코드를 업데이트하여 EventEmitter<HousingLocation>(); 유형의 locationSelectedEvent라는 새 속성을 추가합니다.
@Output() locationSelectedEvent = new EventEmitter<HousingLocation>();

locationSelectedEvent 속성은 @Output()로 장식되므로 이 구성요소의 API의 일부가 됩니다. EventEmitter를 사용하면 HousingLocation 유형을 제공하여 클래스의 제네릭 API를 활용합니다. 이벤트가 locationSelectedEvent에 의해 전송되는 경우, 이벤트 리스너에 포함된 데이터는 모두 HousingLocation 유형일 수 있습니다. 개발을 지원하고 일부 오류의 가능성을 줄이는 유형 안전성입니다.

사용자가 목록에서 위치를 클릭할 때마다 locationSelectedEvent를 트리거해야 합니다.

  1. HousingListComponent를 업데이트하여 housingLocation 유형의 값을 매개변수로 허용하는 selectLocation라는 새 메서드를 추가합니다.
selectHousingLocation(location: HousingLocation) { }
  1. 메서드 본문에서 locationSelectedEvent 이미터로 새 이벤트를 내보냅니다. 방출된 값은 사용자가 선택한 위치입니다.
selectHousingLocation(location: HousingLocation) {
  this.locationSelectedEvent.emit(location);
}

이를 템플릿에 연결해 보겠습니다.

  1. housing-list-component.html에서 기사 요소를 업데이트하여 click event가 있는 새 버튼 하위 요소를 갖도록 합니다. 이 이벤트는 TypeScript 클래스에서 selectHousingLocation 메서드를 호출하고 클릭된 location에 대한 참조를 인수로 전달합니다.
<article *ngFor="let location of results" >
  <p>{{location.name}}</p>
  <button (click)="selectHousingLocation(location)">View</button>
</article>

이제 하우징 위치에 클릭 가능한 버튼이 있으며 값을 다시 구성요소로 전달합니다.

이 프로세스의 마지막 단계는 이벤트를 수신 대기하고 그에 따라 디스플레이를 업데이트하도록 AppComponent를 업데이트하는 것입니다.

  1. app.component.html에서 locationSelectedEvent를 수신 대기하고 updateSelectedLocation 메서드로 이벤트를 처리하도록 app-housing-list 요소를 업데이트합니다.
<app-housing-list [locationList]="housingLocationList" (locationSelectedEvent)="updateSelectedLocation($event)"></app-housing-list>

$event는 템플릿에서 이벤트 핸들러를 처리할 때 Angular에서 제공합니다. $event 인수는 HousingLocation 유형의 객체이므로 EventEmitter&#39의 유형 매개변수를 설정합니다. Angular가 이 모든 작업을 처리합니다. 템플릿이 올바른지 확인하면 됩니다.

  1. app.component.ts에서 HousingLocation | undefined 유형의 selectedLocation라는 새 속성을 포함하도록 코드를 업데이트합니다.
selectedLocation: HousingLocation | undefined;

이는 Union Type이라는 TypeScript 기능을 사용합니다. 유니온을 통해 변수는 여러 유형 중 하나를 허용할 수 있습니다. 이 경우에는 selectedLocation의 기본값을 지정하지 않으므로 selectedLocation의 값이 HousingLocation이나 undefined가 되어야 합니다.

updateSelectedLocation를 구현해야 합니다.

  1. location라는 매개변수와 유형이 HousingLocationupdateSelection라는 새 메서드를 추가합니다.
updateSelectedLocation(location: HousingLocation) { } searchHousingLocations() {}
  1. 메서드 본문에서 selectedLocation 값을 location 매개변수로 설정합니다.
updateSelectedLocation(location: HousingLocation) {
  this.selectedLocation = location;
}

이 부분을 완료하고 마지막 단계는 선택한 위치를 표시하도록 템플릿을 업데이트하는 것입니다.

  1. app.component.html에서 선택한 위치의 속성을 표시하는 데 사용할 새 <article> 요소를 추가합니다. 다음 코드를 사용하여 템플릿을 업데이트합니다.
<article>
  <img [src]="selectedLocation?.photo">
  <p>{{selectedLocation?.name}}</p>
  <p>{{selectedLocation?.availableUnits}}</p>
  <p>{{selectedLocation?.city}}, {{selectedLocation?.state}}</p>
  <p>{{selectedLocation?.laundry ? "Has laundry" : "Does Not have laundry"}}</p>
  <p>{{selectedLocation?.wifi ? "Has wifi" : "Does Not have wifi"}}</p>
 </article>

selectedLocationundefined일 수 있으므로 선택적인 체인 연산자를 사용하여 속성에서 값을 검색합니다. 또한 wifilaundry 부울 값에 3항 구문을 사용합니다. 이렇게 하면 값에 따라 맞춤 메시지를 표시할 수 있습니다.

  1. 코드를 저장하고 브라우저를 확인합니다. 위치를 검색하고 하나를 클릭하여 세부정보를 표시합니다.

두 개의 열 레이아웃, 검색결과가 표시된 왼쪽, 선택한 위치 세부정보를 표시하는 오른쪽

문제가 해결되었지만 아직 해결되지 않은 문제가 있습니다. 페이지가 처음 로드될 때 세부정보 패널에 표시되지 않아야 하는 텍스트 아티팩트가 있습니다. Angular는 다음 단계에서 사용할 콘텐츠를 조건부로 표시할 수 있습니다.

화면에 아티팩트가 잘못 표시되는 기본 UI

지금으로서는 앱이 얼마나 발전해 왔는지 기대됩니다. 지금까지 구현한 내용은 다음과 같습니다.

  • 출력 데코레이터 및 EventEmitter를 사용하여 하위 구성요소의 데이터를 상위 구성요소와 공유할 수 있습니다.
  • 또한 사용자가 값을 입력하고 해당 값을 사용하여 검색할 수 있도록 허용했습니다.
  • 앱이 검색결과를 표시할 수 있으며 사용자가 클릭하여 세부정보를 볼 수 있습니다.

지금까지 잘하셨습니다. 템플릿을 업데이트하고 앱을 완성하세요.

8. 템플릿 설정 변경

UI에는 현재 조건부로 표시되어야 하는 세부정보 패널의 텍스트 아티팩트가 포함되어 있습니다. 두 가지 Angular 기능인 ng-container*ngIf를 사용하겠습니다.

ngIf 지시를 article 요소에 직접 적용하면 사용자가 첫 번째 선택을 할 때 레이아웃 이동이 발생합니다. 이 환경을 개선하려면 article의 하위 요소인 다른 요소에 위치 세부정보를 래핑하면 됩니다. 이 요소에는 스타일 지정 또는 함수가 없으며 DOM에만 가중치가 추가됩니다. ng-container를 사용하면 이를 방지할 수 있습니다. 지시어를 적용할 수는 있지만 최종 DOM에서는 표시되지 않습니다.

  1. app.component.html에서 다음 코드와 일치하도록 article 요소를 업데이트합니다.
<article>
  <ng-container>
  <img [src]="selectedLocation?.photo">
  <p>{{selectedLocation?.name}}</p>
  <p>{{selectedLocation?.city}}, {{selectedLocation?.state}}</p>
  <p>Available Units: {{selectedLocation?.availableUnits}}</p>
  <p>{{selectedLocation?.laundry ? "Has laundry" : "Does Not have laundry"}}</p>
  <p>{{selectedLocation?.wifi ? "Has wifi" : "Does Not have wifi"}}</p>
  </ng-container>
</article>
  1. 다음으로, ng-container 요소에 *ngIf 속성을 추가합니다. 값은 selectedLocation이어야 합니다.
<article>
  <ng-container *ngIf="selectedLocation">
  ...
  </ng-container>
</article>

이제 selectedLocationTruthy인 경우에만 앱에 ng-container 요소의 콘텐츠가 표시됩니다.

  1. 이 코드를 저장하고 페이지가 로드될 때 브라우저에 더 이상 텍스트 아티팩트가 표시되지 않는지 확인합니다.

마지막으로 앱을 업데이트할 수 있습니다. housing-location.component.html의 검색결과에는 더 자세한 내용이 표시됩니다.

  1. housing-location.component.html에서 코드를 다음과 같이 업데이트합니다.
<label for="location-search">Search for a new place</label>
<input id="location-search" #search placeholder="Ex: Chicago"><button
    (click)="searchHousingLocations(search.value)">Search</button>
<article *ngFor="let location of results" (click)="selectHousingLocation(location)">
  <img [src]="location.photo" [alt]="location.name">
  <p>{{location.name}}</p>
  <p>{{location.city}}, {{location.state}}</p>
  <button (click)="selectHousingLocation(location)">View</button>
</article>
  1. 코드를 저장하고 브라우저로 돌아가서 완성된 앱을 표시합니다.

두 열 애플리케이션: 왼쪽에는 검색결과가 표시되고 오른쪽에는 선택한 검색결과의 세부정보가 표시됨

앱이 제대로 작동하고 정상적으로 작동합니다. 잘하셨습니다.

9. 축하합니다

이 여정을 함께하고 페어하우스를 빌드하기 위해 Angular를 사용해 주셔서 감사합니다.

Angular를 사용하여 사용자 인터페이스를 만들었습니다. Angular CLI를 사용하여 구성요소와 인터페이스를 만들었습니다. 그런 다음 Angular의 강력한 템플릿 기능을 이용해 이미지를 표시하고 이벤트를 처리하는 등의 기능을 갖춘 앱을 빌드했습니다.

다음 단계

기능을 계속 빌드하려는 경우 다음과 같은 아이디어를 얻으세요.

  • 데이터는 앱에 하드 코딩됩니다. 좋은 리팩터는 데이터를 포함할 서비스를 추가하는 것입니다.
  • 현재 세부정보 페이지가 같은 페이지에 표시되어 있지만 세부정보를 자체 페이지로 옮기고 Angular 라우팅을 활용하면 좋습니다.
  • 또 다른 업데이트는 휴식 엔드포인트에서 데이터를 호스팅하고 Angular에서 HTTP 패키지를 사용해 런타임 시 데이터를 로드하는 것입니다.

즐길 거리가 많습니다.