Angular 템플릿에서는 템플릿 지역 변수와 템플릿 참조 변수를 선언해서 활용할 수 있습니다.
템플릿 지역 변수(Local template variables): @let
Angular가 제공하는 @let 문법을 사용하면 템플릿에서 지역 변수를 선언해서 재사용할 수 있습니다.
이 방식은 JavaScript let 문법과 비슷합니다.
@let 활용하기
템플릿 지역 변수를 선언하려면 @let을 사용하면 되고, 템플릿 지역 변수의 값은 표현식의 실행 결과로 할당됩니다.
이 값은 바인딩과 비슷하게 Angular가 값이 변경되는 것을 추적합니다.
@let name = user.name;@let greeting = 'Hello, ' + name;@let data = data$ | async;@let pi = 3.1459;@let coordinates = {x: 50, y: 100};@let longExpression = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit ' + 'sed do eiusmod tempor incididunt ut labore et dolore magna ' + 'Ut enim ad minim veniam...';
@let 블록은 각각 변수 하나를 선언합니다.
쉼표(,)를 사용하는 것처럼 블록 하나에서 변수 여러개를 한 번에 선언할 수는 없습니다.
@let으로 값 참조하기
@let으로 변수를 선언하고 나면, 해당 템플릿 안에서는 지역 변수를 자유롭게 사용할 수 있습니다:
@let user = user$ | async;@if (user) { <h1>Hello, {{user.name}}</h1> <user-avatar [photo]="user.photo"/> <ul> @for (snack of user.favoriteSnacks; track snack.id) { <li>{{snack.name}}</li> } </ul> <button (click)="update(user)">Update profile</button>}
재할당 불가
Angular 템플릿이 제공하는 @let은 JavaScript let과 다르게 한 번 선언한 뒤에 값을 재할당할 수 없습니다.
Angular에서는 값을 재할당하지 않아도 표현식의 결과에 따라 가장 최근에 계산된 값이 자동으로 갱신됩니다.
@let value = 1;<!-- 잘못된 문법 - 동작하지 않습니다! --><button (click)="value = value + 1">Increment the value</button>
접근 범위
@let 으로 선언한 변수는 해당 뷰과 해당 뷰의 자식 뷰에서 접근할 수 있습니다.
그리고 @defer 블록이나 구조 디렉티브와 같은 흐름 제어 블록으로 컨텐츠가 동적으로 갱신되는 경우도 변수의 접근 범위에 포함됩니다.
하지만 @let으로 선언한 변수는 호이스팅(hoisting)되지 않기 때문에 부모 뷰나 이웃 뷰에서는 참조할 수 없습니다:
@let topLevel = value;<div> @let insideDiv = value;</div>{{topLevel}} <!-- 유효함 -->{{insideDiv}} <!-- 유효함 -->@if (condition) { {{topLevel + insideDiv}} <!-- 유효함 --> @let nested = value; @if (condition) { {{topLevel + insideDiv + nested}} <!-- 유효함 --> }}{{nested}} <!-- 오류, @if 밖으로 호이스팅되지 않습니다. -->
전체 문법
@let 문법을 자세하게 살펴보면 이렇습니다:
@let키워드- 뒤에 줄바꿈을 제외하고 하나 이상 공백 문자가 옵니다.
- 뒤에 JavaScript 문법으로 유효한 이름이 오고 공백 문자가 올 수 있습니다.
- 뒤에
=심볼이 오고, 공백 문자가 올 수 있습니다. - 뒤에 Angular 표현식이 오며, 이 표현식은 여러 줄일 수 있습니다.
;심볼로 종료됩니다.
템플릿 참조 변수(Template reference variables)
템플릿 참조 변수를 활용하면 템플릿에 있는 엘리먼트를 참조할 수 있습니다.
템플릿 참조 변수는 이런 것들을 가리킬 수 있습니다:
- 템플릿에 존재하는 DOM 엘리먼트 (커스텀 엘리먼트를 포함)
- Angular 컴포넌트나 디렉티브
- ng-template을 의미하는 TemplateRef 객체
그래서 템플릿 참조 변수를 활용하면 템플릿 안에 존재하는 어떤 부분을 다른 쪽에서 참조할 수 있습니다.
템플릿 참조 변수 선언하기
템플릿에 있는 엘리먼트에 변수를 선언하려면 변수 이름 앞에 해시 문자(#)를 붙이면 됩니다.
<!-- `taskInput` 이라는 템플릿 참조 변수를 선언합니다. 이 변수는 HTMLInputElement를 가리킵니다. --><input #taskInput placeholder="Enter task name">
템플릿 참조 변수에 값 할당하기
Angular는 변수가 선언된 엘리먼트를 기준으로 템플릿 변수의 값을 할당합니다.
Angular 컴포넌트에 변수를 선언하면 이 변수는 컴포넌트 인스턴스를 가리킵니다.
<!-- 변수 `startDate`는 `MyDatepicker` 인스턴스를 가리킵니다. --><my-datepicker #startDate />
그리고 <ng-template> 엘리먼트에 템플릿 참조 변수를 선언하면, 이 변수는 템플릿을 의미하는 TemplateRef 인스턴스를 가리킵니다.
자세한 내용은 구조 디렉티브 문서의 Angular가 별표(asterisk, *)를 활용하는 방법 섹션을 참고하세요.
<!-- 변수 `myFragment`는 템플릿 조각을 의미하는 `TemplateRef` 인스턴스를 가리킵니다. --><ng-template #myFragment> <p>This is a template fragment</p></ng-template>
마지막으로 일반 엘리먼트에 템플릿 참조 변수를 선언하면, 이 변수는 HTMLElement 인스턴스를 가리킵니다.
<!-- 변수 `taskInput`는 HTMLInputElement 인스턴스를 가리킵니다. --><input #taskInput placeholder="Enter task name">
Angular 디렉티브 참조하기
Angular 디렉티브는 템플릿에서 참조할 수 있는 이름을 exportAs 프로퍼티로 지정할 수 있습니다:
@Directive({ selector: '[dropZone]', exportAs: 'dropZone',})export class DropZone { /* ... */ }
그러면 엘리먼트에 템플릿 참조 변수를 선언하면서 exportAs를 사용하면 디렉티브 인스턴스를 할당할 수 있습니다:
<!-- 변수 `firstZone`은 `DropZone` 디렉티브 인스턴스를 가리킵니다. --><section dropZone #firstZone="dropZone"> ... </section>
exportAs를 지정하지 않은 디렉티브는 참조할 수 없습니다.
템플릿 참조 변수로 탐색하기
템플릿 변수는 해당 템플릿 안에서 어떤 값을 참조하는 용도 외에도, 컴포넌트나 디렉티브를 탐색 하기 위해 "마킹" 하는 용도로도 사용됩니다.
템플릿에 있는 엘리먼트를 탐색하려면 해당 엘리먼트에 템플릿 변수를 선언하고, 컴포넌트 클래스 코드에서 템플릿 변수 이름으로 탐색하면 됩니다.
<input #description value="Original description">
@Component({ /* ... */, template: `<input #description value="Original description">`,})export class AppComponent { // 템플릿 변수 이름으로 input 엘리먼트를 탐색합니다. @ViewChild('description') input: ElementRef | undefined;}
탐색에 대해 자세하게 알아보려면 쿼리 함수로 자식 컴포넌트 참조하기 문서를 참고하세요.