이 Codelab 정보
1. 소개
게스트 작성자: 아유시 아로라
Angular 요소는 맞춤 요소로 패키징된 Angular 구성요소입니다. 현재 Chrome, Opera 및 Safari에서 지원되며 다른 브라우저에서는 폴리필을 통해 사용할 수 있습니다. Angular 요소에서는 공통 Angular 인터페이스 및 Change Detection Strategy와 함께 전체 Angular 인프라를 활용할 수 있습니다. 이러한 요소는 한 번 등록되면 브라우저 내에서 사용할 수 있습니다.
이 Codelab에서는 자체 image-slider Angular 구성요소를 만드는 과정을 안내한 다음, 이를 Angular 프레임워크 외부에서 작동할 수 있도록 Angular 요소로 변환하는 방법을 설명합니다.
빌드할 항목
이 Codelab에서는 Angular를 사용하여 image-slider 요소를 빌드해 보겠습니다. 이 요소의 특징은 다음과 같습니다.
|
과정 내용
- image-slider 맞춤 구성요소를 만드는 방법
- image-slider 맞춤 구성요소를 맞춤 요소로 변환하는 방법
- 브라우저 내에서 작동하도록 구성요소를 패키징하는 방법
필요한 사항
- 최신 버전의 angular-cli
- 샘플 코드
- 텍스트 편집기
- Angular 구성요소에 관한 기본 지식
이 Codelab에서는 Angular 요소를 중점적으로 설명합니다. 관련 없는 개념과 코드 블록은 자세히 언급되지 않으며 복사하여 붙여넣기만 하도록 제공됩니다.
2. 설정
코드 다운로드하기
다음 링크를 클릭하면 이 Codelab의 모든 코드를 다운로드할 수 있습니다.
다운로드한 ZIP 파일의 압축을 해제합니다. 그러면 루트 폴더 (angular-element-codelab-master)
의 압축이 해제됩니다.
루트 폴더에는 2개의 폴더 (image-slider)
및 (image-slider-finished)
가 들어 있습니다. 모든 코딩 작업은 image-slider라는 디렉터리에서 하게 됩니다.
프로젝트 실행
프로젝트를 실행하려면 루트 디렉터리(image-slider)에서 명령어(ng-serve)를 실행해야 합니다.
앱이 부트스트랩되면 다음이 표시됩니다.
3. Image-Slider 맞춤 구성요소 만들기
이미지 슬라이더를 만드는 방법
이 이미지 슬라이더에서는 Angular 클릭 결합을 사용하여 버튼을 결합합니다. 이미지, 대체 태그, 링크 등을 포함하는 객체 배열을 만들겠습니다. 이러한 이미지를 컨테이너에서 아래로 하나씩 쌓고 클릭 시 컨테이너를 변환하게 됩니다.
image-slider 구성요소를 만든 다음 이 구성요소를 angular-element로 변환해 보겠습니다.
- 이미지 및 제목을 위한 컨테이너
- 데이터를 포함하는 배열
- 데이터를 결합하기 위한 템플릿
4. image-slider 구성요소 구현
프로젝트를 시작하는 방법에는 여러 가지가 있습니다. 이 경우 프로젝트를 최대한 단순하게 유지하고 Angular 요소에 집중하기 위해 CSS와 함께 기본 코드를 제공했습니다.
배열 및 데이터 서비스 만들기
sliderArray에는 다음이 포함된다는 사실을 기억하세요.
- 슬라이더에서 이미지 URL의 img 키
- 이미지 대체 항목을 제공하는 alt 태그
- 이미지에 관한 설명을 제공하는 텍스트
이미 src/assets
디렉터리에 있는 data.json
파일은 다음과 같습니다.
sliderArray = [
{img: 'http://bloquo.cc/img/works/1.jpg', alt: '', text: '365 Days Of weddings a year'},
{img: 'http://bloquo.cc/img/works/2.jpg', alt: '', text: '365 Days Of weddings a year'},
{img: 'http://bloquo.cc/img/works/3.jpg', alt: '', text: '365 Days Of weddings a year'},
{img: 'http://bloquo.cc/img/works/4.jpg', alt: '', text: '365 Days Of weddings a year'},
{img: 'http://bloquo.cc/img/works/5.jpg', alt: '', text: '365 Days Of weddings a year'}
];
서비스를 사용하여 구성요소에서 이 데이터를 가져와야 합니다. data.service.ts
파일에서 @angular/common/http
의 httpClient
모듈을 사용하여 getData()
메서드를 작성합니다. 그러면 이 메서드가 위에서 만든 배열에서 데이터를 가져옵니다.
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http'
const URL = '../assets/data.json';
@Injectable({
providedIn: 'root'
})
export class DataService {
constructor(private http: HttpClient) {}
getData() {
return this.http.get(URL)
}
}
데이터 서비스에서 데이터 가져오기
구성요소 내에서 서비스를 가져와야 합니다. 그러면 observable을 구독하여 data.json
에서 객체를 가져올 수 있습니다.
이를 위해 다음 3단계를 진행해야 합니다.
- 구성요소 배열 초기화
getData()
함수에서 반환된 Observable 구독- observable을 구독한 후 데이터 유형 확인을 위한 인터페이스 Result 생성
- 데이터를 구성요소 배열에 할당
구성요소 배열 초기화하기
객체의 배열인 slider.component.ts
내에서 구성요소 배열을 선언하고 초기화하겠습니다.
선언하려면 다음과 같이 합니다.
sliderArray: object[];
초기화하려면 다음과 같이 합니다.
constructor(private data: DataService) {
this.sliderArray = [];
}
다음으로 생성자 내에서 서비스를 가져와 초기화해야 합니다.
constructor(private data: DataService) {}
이제 서비스를 사용하고 서비스 메서드를 호출할 준비가 되었습니다.
데이터 서비스에서 데이터 가져오기
서비스에서 데이터를 가져오기 위해 getData()
메서드를 호출하고 그 메서드에서 반환하는 observable을 구독하겠습니다. 또한 인터페이스 Result,
를 생성하여 올바른 코드 유형을 가져왔는지 확인할 수 있도록 합니다.
이 작업은 ngOnInit
메서드 내에서 진행합니다.
this.data.getData().subscribe((result: Result)=>{
})
구성요소 배열에 데이터 할당하기
마지막으로 구성요소 배열에 데이터를 할당하겠습니다.
this.data.getData().subscribe((result: Result)=>{
this.sliderArray = result.sliderArray;
})
구성요소 배열 내에서 데이터를 가져오면 이 데이터에 템플릿을 결합할 수 있습니다.
slider.component.html,
에는 이미 HTML 템플릿이 있습니다. 다음 단계는 이 템플릿을 sliderArray
에 결합하는 것입니다.
5. 템플릿에 데이터 결합
*ngFor
지시어를 사용하여 데이터를 템플릿에 결합하고, 마지막으로 템플릿에 변환을 추가하여 슬라이더가 작동하도록 합니다.
여기는 다음 3단계로 이루어집니다.
- 템플릿에
sliderArray
결합 - 슬라이더 버튼에 이벤트 결합 추가
ngStyle
및ngClass
을 사용하여 CSS 변환 추가
구성요소에 slideArray 결합
img-container
, a
text-container
및 a
slider.
를 포함하는 컨테이너가 있습니다.
*ngFor
지시어를 사용하여 세 컨테이너 모두의 데이터를 결합합니다.
<div class="container">
<div class="img-container" *ngFor="let i of sliderArray; let select = index;">
<img src="{{i.img}}" alt="{{i.alt}}" >
</div>
<div>
<div class="text-container">
<div class="page-text" *ngFor="let i of sliderArray;let select = index;">
<h3>{{i.text}}</h3>
</div>
</div>
</div>
</div>
<div class="slider">
<div class="slide-button-parent-container" *ngFor="let i of sliderArray; let x =index">
<div class="select-box">
<div class="slide-button">
</div>
</div>
</div>
</div>
slideArray에 이벤트 결합하기
데이터가 결합되면 Angular click binding
을 사용하여 클릭 이벤트를 모든 slide-button에 결합합니다. selected(x)
라는 함수를 만듭니다. 여기서 x는 배열의 색인입니다.
selected(x) {
this.downSelected(x);
this.selectedIndex = x;
}
downSelected(i) {
this.transform = 100 - (i) * 50;
this.selectedIndex = this.selectedIndex + 1;
if(this.selectedIndex > 4) {
this.selectedIndex = 0;
}
}
여기서 유념할 사항은 다음과 같습니다.
- 세부 선택된 함수는
selected
함수 클릭 시 색인에서 전달된 변환 속성의 값을 1/50로 줄입니다. - 이 로직은 텍스트 컨테이너를 100%, 50%, -50%, -100%로 변환하고 그 결과 네 가지 서로 다른 상태가 생성됩니다.
ngStyle 및 ngClass를 사용하여 CSS 변환 추가하기
처음에는 모든 이미지를 불투명도 0으로 설정하고 선택한 색인이 이미지 색인과 같아지면 ngClass directive
를 사용하여 selected
클래스를 추가합니다. 이 selected
클래스는 이미지가 사용자에게 보이도록 이미지에 불투명도 1을 추가합니다.
<div class="img-container" *ngFor="let i of sliderArray; let select = index;"
[ngClass]="{'selected': select == selectedIndex}">
</div>
그런 다음 select()
함수를 사용하여 계산된 transform
값에 따라 text-container를 변환합니다.
<div [ngStyle]="{'transform': 'translateY('+ transform + '%' +')', 'transition': '.8s'}">
</div>
이 모든 단계를 진행하면 아래와 같은 최종 코드가 표시됩니다.
<div class="container">
<div class="img-container" *ngFor="let i of sliderArray; let select = index;"
[ngClass]="{'selected': select == selectedIndex}">
<img src="{{i.img}}" alt="{{i.alt}}" >
</div>
<!--</div>-->
<div [ngStyle]="{'transform': 'translateY('+ transform + '%' +')', 'transition': '.8s'}">
<div class="text-container">
<div class="page-text" *ngFor="let i of sliderArray;let select = index;" [ngClass]="{'selected': select == selectedIndex}">
<h3>{{i.text}}</h3>
</div>
</div>
</div>
</div>
<div class="slider">
<div class="slide-button-parent-container" *ngFor="let i of sliderArray; let x =index" (click)="selected(x)" >
<div class="select-box">
<div class="slide-button" [ngClass]="{'slide-button-select': x == selectedIndex}" >
</div>
</div>
</div>
</div>
6. 구성요소를 Angular 요소로 변환
이 절차는 다음 5단계로 구성됩니다.
- Angular 요소에
Shadow DOM
사용 entryComponents
활용@angular/elements
에서CreateCustomElement
모듈 가져오기 및 사용custom-element
정의ngDoBootstrap
메서드 실행
Angular 요소에 Shadow DOM 사용하기
이제 image-slider가 실행되고 있으므로 이를 Angular Element
로 만들기만 하면 됩니다.
흥미로운 사실은 구성요소 DOM 즉, Shadow DOM을 만드는 데 약간의 변경만 하면 된다는 점입니다.
ViewEncapsulation
모듈을 가져와서 ShadowDom
메서드를 사용해야 합니다.
@Component({
selector: 'app-slider',
templateUrl: './slider.component.html',
styleUrls: ['./slider.component.css'],
encapsulation: ViewEncapsulation.ShadowDom
})
entryComponent 활용
entry 구성요소는 Angular에서 필수적으로 로드되는 구성요소입니다. entry 구성요소는 NgModule에서 부트스트랩하여 지정합니다.
여기서는 @NgModule
내의 entryComponents
배열에 SliderComponent
를 지정합니다.
@NgModule({
declarations: [
SliderComponent
],
imports: [
BrowserModule,
HttpClientModule
],
})
createCustomElement 모듈 가져오기 및 사용
여기에서는 @angular/elements.
의 createCustomElement
모듈을 사용해야 합니다. SliderComponent,
를 createCustomElement
함수의 매개변수로 사용해야 합니다. 그런 다음 DOM에 slider
를 등록해야 합니다.
import { createCustomElement } from '@angular/elements';
export class AppModule {
constructor(private injector: Injector) {
const slider = createCustomElement(SliderComponent, { injector });
}
}
슬라이더를 DOM 요소로 등록하려면 customElements.define
메서드를 사용하여 슬라이더를 정의합니다.
customElements.define('motley-slider', slider);
마지막으로 ngDoBootstrap()
메서드를 사용하여 이 custom-element를 부트스트랩해야 합니다. 전체 코드는 다음과 같습니다.
import { BrowserModule } from '@angular/platform-browser';
import { NgModule, Injector } from '@angular/core';
import { createCustomElement } from '@angular/elements';
import { SliderComponent } from './slider/slider.component';
import { HttpClientModule} from "@angular/common/http";
@NgModule({
declarations: [
SliderComponent
],
imports: [
BrowserModule,
HttpClientModule
],
})
export class AppModule {
constructor(private injector: Injector) {
const slider = createCustomElement(SliderComponent, { injector });
customElements.define('motley-slider', slider);
}
ngDoBootstrap() {}
}
Angular 요소 패키징
새 명령어로 package.json
을 수정해야 합니다. package.json
파일 내의 스크립트 객체를 수정합니다.
수정된 스크립트 객체를 확인해 보겠습니다.
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build --prod --output-hashing=none",
"package": "cat dist/my-app/{runtime,polyfills,scripts,main}.js | gzip > elements.js.gz",
"serve": "http-server",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
}
이제 ng build & ng package
명령어를 실행할 수 있습니다. 마지막으로 ng serve를 실행하여 build 명령을 사용하여 생성된 dist/ 폴더를 제공합니다. 또한 ng package
명령어에서 얻은 gzip
을 사용하고 압축을 푼 다음 npm module
로 게시할 수 있습니다.