티스토리 뷰
Angular : Custom Structural(구조적) Directive 생성하기
Korean Eagle 2020. 6. 10. 00:261. 이 포스트는 structural directive를 생성하는 방법에 대한 내용이다.
2. 설명은 ngFor 처럼 반복하는 구문이지만 특정한 횟수를 단순히 반복하는 기능의 directive를 구현한다.
2-0 개발 하다 보면 이 기능이 필요한 경우가 상당히 많다.
2-1 하지만, 단순히 n회 반복하는 구문을 작성하려면 컴포넌트 클래스에 배열까지 생성해야 해서 귀찮다.
2-2 바로 이전에 구현한 pagenation 역시 총 자료의 갯수만큼 반복하여 숫자를 나열하는 로직을 가지고 있다.
3. 예제는 아래 pagenation 포스트를 가지고 설명한다.
4. 순서는 Directive이기 때문에 직전 포스트와 동일하다.
5. Directive 생성
5-1 아래 처럼 실행하면 빈 TimesDirective클래스가 생성되고 app.module.ts에도 자동으로 등록된다.
$ ng generate directive times
6. times.directive.ts 파일
6-1 2개의 Ref타입의 컴포넌트를 주입받는다. ViewContainerRef, TemplateRef 이다.
6-1-1 ViewContainerRef는 해당 directive가 지정된 element 자체를 참조한다.
6-1-1-1 ElementRef와 유사한 것 같지만,
6-1-1-2 ViewContainerRef는 컨테이너 기능이 특화되어 내부에 자식 element를 추가,삭제 할 수있다.
6-1-1-3 아래 로직을 보면 알겠지만, 이 컨테이너에 자식 element를 받은 인자값 만큼 추가하는 것이 전부이다.
6-1-2 TemplateRef는 directive가 지정된 element의 자식 element를 참조한다.
6-2 *appTimes로 지정이 되면 여기에 대입되는 값은 @Input('appTimes')로 접근할 수 있고 인자로 값을 받아온다.
6-2-1 appTimes 아닌 별도의 속성값을 사용하여 값을 받아올 수도 있지만 클래스 이름과 동일하게 하는 경우가 많다.
6-2-2 인자로 받은 숫자만큼 반복하는 로직을 보면
6-2-2-1 viewContainerRef내에 자식을 추가하는 createEmbeddedView를 사용하고 있다.
6-2-2-2 이 두번째 인자는 ngFor의 exported value와 동일한 쓰임새로 사용되고 아래의 경우는 index가 지정된다.
6-2-2-3 exported value에 대한 내용은 아래의 링크를 참조한다.
import { Directive, ViewContainerRef, TemplateRef, Input } from '@angular/core';
@Directive({
selector: '[appTimes]'
})
export class TimesDirective {
constructor(
private viewContainer: ViewContainerRef,
private templateRef: TemplateRef<any>
) { }
@Input('appTimes') set render(times: number) {
this.viewContainer.clear()
for (let i = 0; i < times; i++) {
this.viewContainer.createEmbeddedView(this.templateRef, {
index: i
})
}
}
}
7. 사용하기
7-1 app.component.html
7-1-1 ngFor 구문이 사라지고 *appTimes로 대체되어 있다.
<div class="container">
<nav>
<ul class="pagination">
<li class="page-item" [appClass]="{ disabled: currentPage === 0 }">
<a (click)="currentPage = currentPage - 1" class="page-link">Prev</a>
</li>
<ng-container *appTimes="images.length; let i=index;">
<li [appClass]="getClass(i)" class="page-item" (click)="currentPage = i"
*ngIf="checkWindowIndex(i)">
<a class="page-link">{{ i + 1 }}</a>
</li>
</ng-container>
<li class="page-item" [appClass]="{ disabled: currentPage === images.length-1 }">
<a class="page-link" (click)="currentPage = currentPage + 1">Next</a>
</li>
</ul>
</nav>
<div>
<h4>{{ images[currentPage].title }}</h4>
<img [src]="images[currentPage].url" alt="">
</div>
</div>
7-2 설명할 것은 없지만 완결성을 위해 app.component.ts를 추가한다.
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
currentPage = 0
images = [
{
title: 'At the Beach',
url: 'https://images.unsplash.com/photo-1552379080-7bf7d131b129?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80'
},
{
title: 'At the Beach',
url: 'https://images.unsplash.com/photo-1475503572774-15a45e5d60b9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80'
},
{
title: 'At the Beach',
url: 'https://images.unsplash.com/photo-1496046744122-2328018d60b6?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1064&q=80'
},
{
title: 'At the Beach',
url: 'https://images.unsplash.com/photo-1502860372601-2a663136d5a2?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1132&q=80'
},
{
title: 'At the Beach',
url: 'https://images.unsplash.com/photo-1552379080-7bf7d131b129?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80'
},
{
title: 'At the Beach',
url: 'https://images.unsplash.com/photo-1475503572774-15a45e5d60b9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80'
},
{
title: 'At the Beach',
url: 'https://images.unsplash.com/photo-1496046744122-2328018d60b6?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1064&q=80'
},
{
title: 'At the Beach',
url: 'https://images.unsplash.com/photo-1502860372601-2a663136d5a2?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1132&q=80'
},
]
getClass(value: number): any {
const classes: any = {}
if (value === this.currentPage) {
classes.active = true
} else {
classes.active = false
}
return classes
}
checkWindowIndex(value: number): boolean {
return Math.floor(this.currentPage/10) === Math.floor(value/10)
}
}
'Client Technologies > Angular' 카테고리의 다른 글
Angular : 모듈단위 라우팅 설정하기 (0) | 2020.06.12 |
---|---|
Angular : Module 기본 (0) | 2020.06.12 |
Angular : Custom Attribute(속성) Directive 생성하기 (0) | 2020.06.09 |
Angular : if-else 구조적 Directive template 몇 개 (0) | 2020.06.09 |
Angular : Pagenation 구현하기 (0) | 2020.06.09 |
- Total
- Today
- Yesterday
- 도커 개발환경 참고
- AWS ARN 구조
- Immuability에 관한 설명
- 자바스크립트 멀티 비동기 함수 호출 참고
- WSDL 참고
- SOAP 컨슈머 참고
- MySql dump 사용법
- AWS Lambda with Addon
- NFC 드라이버 linux 설치
- electron IPC
- mifare classic 강의
- go module 관련 상세한 정보
- C 메모리 찍어보기
- C++ Addon 마이그레이션
- JAX WS Header 관련 stackoverflow
- SOAP Custom Header 설정 참고
- SOAP Custom Header
- SOAP BindingProvider
- dispatcher 사용하여 설정
- vagrant kvm으로 사용하기
- git fork, pull request to the …
- vagrant libvirt bridge network
- python, js의 async, await의 차이
- go JSON struct 생성
- Netflix Kinesis 활용 분석
- docker credential problem
- private subnet에서 outbound IP 확…
- 안드로이드 coroutine
- kotlin with, apply, also 등
- 안드로이드 초기로딩이 안되는 경우
- navigation 데이터 보내기
- 레이스 컨디션 navController
- raylib
- hibernate
- Spring
- Rest
- one-to-many
- 스프링부트
- 상속
- Security
- 하이버네이트
- XML
- 매핑
- 설정하기
- 설정
- Many-To-Many
- mapping
- 로그인
- crud
- Validation
- 스프링
- spring boot
- WebMvc
- jsp
- 자바
- one-to-one
- 외부파일
- MYSQL
- Spring Security
- Angular
- RestTemplate
- form
- login