모듈에서 다양한 기능을 사용할 수 있게 import를 통해서 외부 모듈을 참조하도록 하였습니다.
Angular에서는 마치 컴포넌트에 주사기로 넣어주듯이 데이터를 전달 해줄수 있습니다.
Inject를 사용하는 방법
데이터 생성 및 공유
/src/app/MyTypes.ts
export declare type INFORMATION = { // 전달할 데이터 양식
data1 : string,
data2 : number,
data3 : any,
}
export const myData : INFORMATION = { // 내가 전달할 데이터
data1 : 'data',
data2 : 1433,
data3 : ['data3_1','data3_2'],
}
전달할 데이터 양식과 해당하는 데이터를 만들어 줍니다.
export라는 명령어를 붙여서 외부에서 사용가능한 변수로 바꾸어 줍니다.
기존 app모듈에서 만들어 놓은 myData를 공유하는 기능을 추가합니다.
app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { LoginComponent } from './login/login.component';
import {FormsModule, ReactiveFormsModule} from "@angular/forms";
import { DashboardComponent } from './dashboard/dashboard.component';
import { myData } from "./MyType";
@NgModule({
declarations: [
AppComponent,
LoginComponent,
DashboardComponent
],
imports: [
BrowserModule, FormsModule,
ReactiveFormsModule //반응형 폼 사용
],
providers: [
{provide:"sending_name", useValue:myData}
],
bootstrap: [AppComponent]
})
export class AppModule { }
provider
부분에 json형식으로 추가하여 줍니다.
데이터 사용방법
login컴포넌트 파일에서 해당 데이터를 불러와 보겠습니다.
login.component.ts
import { Component, OnInit, Input, Output, EventEmitter, Inject } from '@angular/core'; //Inject를 추가하여 줍니다.
import { INFORMATION } from '../MyType'; //새로만든 타입을 추가 해 줍니다.
//..생략
export class LoginComponent implements OnInit {
//..생략
constructor(@Inject("sending_name") my_type : INFORMATION) {
console.log(my_type);
}
//..생략
}
constructor부분을 아래처럼 수정합니다.
@inject
데코레이터를 이용해서 원하는 data의 key값을 넣으면 해당 데이터를 불러 올수 있습니다.
app모듈에서 providers에 json형식으로 데이터를 입력하였습니다.
형태 : {provide : 이름, useValue : 값}
이러한 app모듈이 전달한 데이터는 컴포넌트에서 생성자를 통해서 받습니다.
데이터를 받을때 @Inject
데코레이터가 사용이 되며 소괄호에 provide를 통해 지어준 이름값을 입력하면 됩니다.
Service를 사용하는 방법
상위 컴포넌트에서 하위 컴포넌트에게 데이터를 전달하고 받기 위해서 Input과Output 데코레이터를 이용 했습니다.
하지만 컴포넌트의 종류와 갯수가 많아진다면 해당 작업을 해야하는 대상도 엄청나게 많아질 것입니다.
그것을 해결하기 위해 나온것이 서비스 입니다
$ ng g service myService
명령어를 입력해 봅시다
컴포넌트를 만들 때 처럼 위 명령어는 서비스 형태의 클래스를 만드는 명령어 입니다.
서비스 클래스를 생성할 때는 $ ng g service “이름”
의 형태로 입력을 하면 됩니다.
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class MyServiceService {
constructor() { }
}
서비스는 @Injectable
이라는 데코레이터가 존재하며 일반 타입스크립트 형식의 클래스 모양만 존재 합니다.
전달할 데이터를 서비스에 붙여 넣어 보겠습니다.
import { Injectable } from '@angular/core';
import { INFORMATION } from './MyType';
@Injectable({
providedIn: 'root'
})
export class MyServiceService {
public readonly myData : INFORMATION = { //내가 전달할 데이터
data1 : 'data1',
data2 : 1433,
data3 : ['data3_1','data3_2']
};
constructor() {
}
}
app.module.ts를 수정하여 줍니다.
@NgModule({
declarations: [
AppComponent,
LoginComponent,
DashboardComponent
],
imports: [
BrowserModule, FormsModule,
ReactiveFormsModule //반응형 폼 사용
],
providers: [
MyServiceService // MyServiceService를 제공
],
bootstrap: [AppComponent]
})
export class AppModule { }
데이터를 받을 login컴포넌트 파일도 수정해 줍니다.
login.conponent.ts
constructor(service : MyServiceService) {
console.log(service)
}
login컴포넌트에서 생성자를 통해 데이터를 받는 부분이 매우 간결해 졌습니다.
전달한 데이터가 잘 출력되는 모습입니다.
서비스를 이용한 로그인 구현 심화
서비스에 코드를 추가합니다.
my-service.service.ts
import { Injectable } from '@angular/core';
import { INFORMATION } from './MyType';
import { BehaviorSubject, Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class MyServiceService {
public readonly myData : INFORMATION = { //내가 전달할 데이터
data1 : 'data1',
data2 : 1433,
data3 : ['data3_1','data3_2']
};
constructor() {
}
private FACTORY : BehaviorSubject<any> = new BehaviorSubject({}); //??
public readonly TV: Observable<any> = this.FACTORY.asObservable(); //??????
public addData(arg : boolean, loginInfomation? : any) : void{
if(arg){
this.FACTORY.next(loginInfomation); //????
}
}
}
또한 login컴포넌트와 app컴포넌트를 수정해봅시다.
login.component.ts
import { Component, OnInit, Input, Output, EventEmitter, Inject } from '@angular/core';
import { FormControl } from '@angular/forms';
import { Validators } from '@angular/forms';
import { MyServiceService } from '../my-service.service';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
//@Input() visible1 : boolean; //이제 필요가 없습니다.
//@Output() sendMyEvent : EventEmitter<any> = new EventEmitter();
id = new FormControl('');
pwd = new FormControl('', [ Validators.required, Validators.minLength(4) ]);
private message;
styleArray = {'wrong_id':false, 'wrong_pwd':false};
constructor(private service : MyServiceService) {
}
ngOnInit(): void {
}
tryToLogin() : void{
console.log(this.pwd)
if(this.id.value =='admin' && this.pwd.value == '1234'){
alert('로그인합니다!');
this.service.addData(true, {id:'admin', name:'사용자'}); //서비스에 addData 함수를 호출, 로그인 성공값을 전달 합니다.
} else if(this.id.value != 'admin'){
this.setMessage = 'wrong id';
this.styleArray.wrong_id = true;
this.styleArray.wrong_pwd = false;
} else if(this.pwd.value != '1234'){
this.setMessage = 'wrong pwd';
this.styleArray.wrong_id = false;
this.styleArray.wrong_pwd = true;
}
}
set setMessage(arg){
this.message = arg;
}
get getMessage() : any{
return this.message;
}
}
다음은 컴포넌트 html을 수정합니다.
<app-login *ngIf="loginBool"></app-login>
<app-dashboard *ngIf="boardBool"></app-dashboard>
마지막으로 app컴포넌트를 수정합니다
import { Component } from '@angular/core';
import { MyServiceService } from './my-service.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
loginBool = true;
boardBool = false;
constructor(private service : MyServiceService){
service.TV.subscribe( arg=>{
if(arg && arg.id){
console.log('로그인이 성공했군요 : ',arg);
this.loginBool = false;
this.boardBool = true;
}
});
}
}
여기서 서비스를 보면 서비스에는 2가지 형태의 클래스가 존재합니다.
BehaviorSubject
와 Observable
2가지가 존재합니다.
BehaviorSubject
클래스는 데이터의 변화에 대해서 마치 공장처럼 발행을 하는 클래스 입니다.
이는 next라는 함수를 통해서 데이터를 전달합니다.
Observable
클래스는 BehaviorSubject 클래스를 바라보는 구독자 입니다.
BehaviorSubject
클래스가 next로 행위를 전달하면 구독하는 Observable
클래스가 그 행동에 대한 행위를 실시 합니다.
정리
여기까지 앵귤러에서의 “데이터 공유기법”에 대해 살펴 보았습니다.
이는 의존성 주입(DI)이라는 내용으로 많이 불리웁니다.
서비스는 모듈에서 제공(provider)되어야 하며, 컴포넌트에서는 생성자(constructor)를 통해 공급 받습니다.
데이터 변경에 따른 이벤트를 손쉽게 구현 하려면 BehaviorSubject
클래스와, Observable
클래스를 사용합니다.
BehaviorSubject
클래스는 이벤트를 만들어 내는, 채팅앱과 같은 기능을 담당하며, next
함수를 통해 이벤트를 발생시킵니다.
Observable
클래스는 이벤트를 구독하는 채팅앱을 사용하는 사용자이며, subscribe
함수를 통해 이벤트에 대한 행위를 정의 합니다.
참고
https://lts0606.tistory.com/365