Promise 기반 대화 상자 결과를 사용하여 모달 대화 상자 함수를 Angular로 구현하기 > 블로그 & Tips

본문 바로가기

Wijmo

블로그 & Tips

Promise 기반 대화 상자 결과를 사용하여 모달 대화 상자 함수를 Angular로 구현하기

페이지 정보

작성자 GrapeCity 작성일 21-06-08 10:16 조회 403회 댓글 0건

본문

웹 응용 프로그램의 모달 대화 상자

웹 응용프로그램에서 사용할 모달 대화 상자의 스타일을 선택할 때 확인 함수와 같이 기본 JavaScript 대화 상자처럼 사용하기 쉬운 대화 상자를 원합니다.

if(confirm('Do you agree?')) {
    do_it();
}

JavaScript의 기본 alert/confirm/prompt 함수는 기능 및 사용자 정의 옵션과 관련되면 매우 제한적이라는 문제가 있습니다. Angular 개발자는 편리한 Angular로 콘텐츠 및 동작을 정의할 수 있는 대화 상자를 만들 수 있기를 원할 것입니다. 대화 상자를 표시하는 것은 단일 함수 호출로 래핑될 수 있으며, 대화 상자 결과의 비동기식 처리는 간단하고 명확한 코드로 구현될 수 있습니다. 

이 포스팅에서는 이와 같은 요구 사항과 일치하는 대화 상자 함수 라이브러리를 구현하는 비교적 간단한 방법을 살펴볼 것입니다. 이러한 구현에서 대화 상자 콘텐츠와 동작은 임의의 Angular 컴포넌트로 표현할 수 있으며, 대화 상자는 대화 상자 결과를 Promise 개체로 반환하는 전용 함수로 표시할 수 있습니다.


JavaScript Promise

Promise는 비동기 실행 결과를 기다리는 하나의 코드(Promise 클라이언트)가 해당 결과를 생성하는 다른 코드(Promise 공급자)와 통신하도록 허용하는 개체입니다. JavaScript Promise를 완전히 이해하지 못하셨다면 Promise에 대해 자세히 설명하는 유용한 문서를 살펴 보세요.

Promise 공급자는 Promise 객체를 만들고, Promise 클라이언트는 then().catch() 메서드를 사용하여 결과를 "구독"할 수 있습니다.

promise.then(resultCallback).catch(rejectCallback);

위 행은 블로킹되지 않으므로, 컨트롤을 즉시 리턴하고 코드의 다음 행에서 계속 실행됩니다. Promise 공급자에서 결과가 있음을 인식하면(예: XMLHttpRequest가 완료됨) Promise가 반환 데이터와 함께 Promise 클라이언트의 resultCallback을 호출하도록 하는 특수 작업을 수행합니다. Promise 공급자에서 문제가 있음을 감지하면(예: XMLHttpRequest에 실패) 오류 데이터와 함께 rejectCallback을 호출합니다. 

resultCallback으로 전달된 결과 데이터는 Promise가 될 수 있습니다. 즉, .then().catch() 호출 체인을 만들 수 있습니다.

promise.then(result1Callback).then(result2Callback).catch(reject1Callback).then(result3Callback).catch(reject2Callback);


기본 아키텍처


핵심 showComponentInPopup 함수

대화 상자 구현의 핵심은 다음 작업을 수행할 수 있는 Low-Level의 showComponentInPopup 함수입니다.

  • 임의의 Angular 컴포넌트의 인스턴스 만들기, 특정 값을 사용하여 속성 초기화, 화면의 대화 상자 창(대부분의 경우 모달)에 표시

  • 대화 상자와의 사용자 상호 작용 결과를 Promise로 반환

구현 결과는 다음과 같을 수 있습니다.

showComponentInPopup(dialogWindowProperties, componentToShow, componentProperties).then(result => {/*process dialog result*/}).catch(error => {*/process error*/});


특정 대화 상자 함수

showComponentInPopup 함수가 있으면 다음 특정한 종류의 대화 상자 함수 라이브러리를 만들 수 있습니다.

yesNoDialog('Do you accept?').then(() => /*do something if Yes*/).catch(() => /*do something if Not*/);

또는

loginDialog(ownerElement).then((data) => /*process successful authorization*/).catch((error) => /*process authorization failure*/);


그 외에도 다양하게 만들 수 있습니다. 이 작업을 수행하려면 다음과 같이 하십시오.

  • 대화 상자 콘텐츠를 나타내고, 사용자의 대화 상자 상호 작용의 결과를 포함하며, 일부 서비스와 대화 상자의 상호 작용 결과를 포함할 수 있는 특정 Angular 컴포넌트를 만듭니다.

  • showComponentInPopup 함수를 호출하고 컴포넌트 유형과 초기화 속성 값을 함수 매개 변수로 전달하는 바로 가기 함수를 만듭니다.


구현


showComponentInPopup 함수

showComponentInPopup 함수와 바로 가기 함수의 라이브러리는 app/dialog.service.ts 파일에서 구현됩니다. 이 함수의 코드는 아래에 나와 있습니다.

import { Component, ComponentFactoryResolver, Injectable, ViewContainerRef, EventEmitter } from '@angular/core';
​
import * as wjcInput from '@grapecity/wijmo.input';
​
export function showComponentInPopup(popupOptions: any, componentType: any, componentProperties: any, vcr: ViewContainerRef, cmpResolver: ComponentFactoryResolver): Promise<any> {
// Create and initialize the Wijmo PopUp
let hostEl = document.createElement('div'), popUp = new wjcInput.Popup(hostEl);
popUp.hideTrigger = wjcInput.PopupTrigger.None;
popUp.initialize(popupOptions);
​
// Create the dialog content component instance and initialize its properties
let cmpRef = vcr.createComponent(cmpResolver.resolveComponentFactory(componentType));
if(componentProperties) {
  for(let prop in componentProperties) {
    cmpRef.instance[prop] = componentProperties[prop];
  }
}
​
// Add the component to the Popup
popUp.content = cmpRef.location.nativeElement;
​
// Add handler to the popUp.hidden event that will destroy the popUp and contained component
let hiddenEh = () => {
  popUp.hidden.removeHandler(hiddenEh);
  cmpRef.destroy();
  popUp.owner = null;
  hostEl.parentElement.removeChild(hostEl);
  popUp.dispose();
}
popUp.hidden.addHandler(hiddenEh);
​
// Show the PopUp
popUp.show(false);
​
// The function's return value, assigned with a Promise representing the dialog result
let ret = (<IPromiseResult>cmpRef.instance).result;
// Add this .then.catch branch to the returning Promise that hides the Popup after the component's 'result' will be resolved or rejected
// Note that this branch is not visible to the client code
ret.then((data) => {
  popUp.hide();
}).catch((error) => {
  popUp.hide();
})
​
return ret;
}

이 구현을 둘러보면서 몇 가지 중요한 부분을 살펴보겠습니다.


팝업

모달 "창"에 콘텐츠를 표시할 수 있는 몇 가지 UI 요소가 필요합니다.

이 예에서는 UI 요소에 Wijmo Popup 컨트롤을 사용합니다. 또한 부트스트랩 모달 팝업과 같은 다른 도구도 자유롭게 사용할 수 있습니다. showComponentInPopup 함수의 첫 번째 매개 변수는 popupOptions로, Popup 관련 속성 값과 함께 해시 객체를 전달할 수 있습니다.

예를 들어, 대화 상자를 화면 가운데 배치하는 대신 일부 DOM 요소에 고정된 대화 상자를 보여주려고 할 수 있습니다. 이러한 경우 다음의 옵션 값을 넘겨 주어야 합니다.

{ owner: anchorElement }

위 요소를 매개 변수 값으로 전달하면 Popup이 시각적으로 anchorElement에 고정하도록 지시합니다. 다음 코드는 전달된 Popup 속성 값을 사용하여 Popup 인스턴스를 만들고 초기화합니다.

let hostEl = document.createElement('div'), popUp = new wjcInput.Popup(hostEl);
popUp.hideTrigger = wjcInput.PopupTrigger.None;
popUp.initialize(popupOptions);


대화 상자 콘텐츠로서의 컴포넌트

이제, 대화 상자 콘텐츠로 사용되는 컴포넌트를 인스턴스화하고 그 속성을 초기화해야 합니다. 이 함수는 콘텐츠 컴포넌트와 관련된 매개 변수 2개를 정의하는데, 컴포넌트 유형(생성자 함수에 대한 참조)을 수신하는 componentType과 컴포넌트 속성 값을 사용하여 해시 객체를 전달할 수 있는 componentProperties입니다. 그런데 이 함수 정의에는 명확하지 않은 매개 변수 2개가 있습니다.

vcr: ViewContainerRef, cmpResolver: ComponentFactoryResolver

해당 매개 변수는 (코드에서) 동적으로 컴포넌트의 인스턴스를 만드는 데 필요한 Angular 서비스에 대한 참조로, 대화 상자 함수를 호출하는 컴포넌트 생성자의 매개 변수로 삽입하여 얻을 수 있습니다.

Angular에서 동적으로 컴포넌트를 만드는 방법에 대해 자세히 알아보려면 Angular 팀에서 해당 프로세스를 자세히 설명하기 위해 작성한 문서를 참조하십시오.

해당 매개 변수는 이 코드에서 다음 행으로 변환됩니다.

let cmpRef = vcr.createComponent(cmpResolver.resolveComponentFactory(componentType));

이 코드는 컴포넌트를 생성하고 연결된 ComponentRef 인스턴스(컴포넌트에 대한 유용한 정보 포함)를 cmpRef 변수에 할당합니다. cmpRef.instance 속성은 인스턴스화된 컴포넌트에 대한 참조를 포함하고 있으며, cmpRef.location.nativeElement는 인스턴스화된 컴포넌트의 템플릿을 나타내는 루트 DOM 요소를 가져오는 데 사용할 수 있습니다. 컴포넌트가 생성된 후 componentProperties 매개 변수에 전달된 값을 사용하여 해당 속성을 할당합니다.

if(componentProperties){
    for(let prop in componentProperties) {
      cmp.instance[prop] = componentProperties[prop]'
    }
}

컴포넌트의 DOM을 Popup에 추가하면 팝업의 콘텐츠는 컴포넌트의 템플릿이 됩니다.

popUp.content = cmpRef.location.nativeElement;

마지막으로, 화면에 컴포넌트를 표시할 수 있습니다.

popUp.show(false);


대화 상자로서의 Promise

모든 JavaScript 사용자 정의 대화 상자 구현은 본질적으로 비동기식입니다. 기본 alert, confirm, prompt 함수와 같은 방식으로 구현할 수 없고, 여기서 코드 실행은 사용자가 대화 상자에서 버튼을 누를 때까지 차단됩니다. 대화 상자는 사용자가 지정한 예측할 수 없는 순간에 결과를 반환해야 하며, 더 복잡한 시나리오에서는 일부 비동기 서비스에 의해 결과를 반환해야 합니다. 예를 들어, 사용자가 LoginDialog에서 확인 버튼을 누르면 후자는 서버에 인증 요청을 보내고 응답을 대기할 수 있습니다. 응답을 수신한 후에만 대화 상자 결과를 처리할 준비가 됩니다.

비동기 결과를 처리하기 위한 가장 편리한 최신 방법은 Promise에서 제공합니다. 비동기 함수 결과가 Promise 객체이면 클라이언트 코드는 호출의 .then().catch() 체인을 함수에 추가해야 하는데, 여기서 결과를 처리하는 처리기 함수는 매개 변수로 전달됩니다. 이는 구현 시 사용할 접근 방식입니다.

대화 상자 결과는 사용자 정의 대화 상자 콘텐츠 구성 요소에 의해 생성되며 컴포넌트의 의미 체계에 따라 다릅니다. 결과는 Promise 유형의 컴포넌트 속성으로 노출될 수 있습니다. showComponentInPopup 함수는 해당 속성이 무엇인지 알고, 임의의 컴포넌트에서 이 결과를 읽을 수 있으며, 읽은 결과를 함수 결과로 반환할 수 있어야 합니다. 즉, 함수가 컴포넌트에서 결과를 가져오는 방법을 알 수 있도록 함수와 콘텐츠 컴포넌트 간 계약에 서명해야 합니다.

다음 인터페이스를 도입하여 이 계약을 공식화할 것입니다.

export interface IPromiseResult {
    readonly result: Promise<any>;
}

대화 상자 콘텐츠 컴포넌트는 대화 상자 결과를 result 속성이 반환하는 Promise 객체로 저장하는 이 인터페이스를 구현해야 합니다. 이 계약을 적용하면 컴포넌트에서 대화 상자 결과를 쉽게 검색하여 함수 결과로 반환할 수 있습니다.

let ret = (<IPromiseResult>cmpRef.instance).result;
return ret;

그러나 showComponentInPopup 함수는 기능을 하나 더 구현해야 합니다. 즉, 대화 상자 결과가 준비되면(즉, Promise가 확인 또는 거부됨) 팝업을 닫아야 합니다. 함수를 호출하는 코드에 이러한 기능을 삽입하는 것은 적절하지 않습니다. 이를 위해, 함수는 반환되는 Promise에 .then().catch() 체인을 추가하고 팝업을 숨깁니다.

이 작업을 처리하는 전체 코드 조각은 다음과 같습니다.

// The function's return value, assigned with a Promise representing the dialog result
let ret = (<IPromiseResult>cmpRef.instance).result;
// Add this .then.catch branch to the returning Promise that hides the Popup after the component's 'result' will be resolved or rejected
// Note that this branch is not visible to the client code
ret.then((data) => {
popUp.hide();
}).catch((error) => {
popUp.hide();
})
​
return ret;

따라서 함수는 .then().catch() 체인을 반환되는 Promise에 추가했고 이 함수를 호출하는 응용 프로그램 코드는 대화 상자 결과를 처리하기 위해 동일한 Promise에 유사한 .then().catch() 체인을 추가합니다. 동일한 Promise에 다른 체인 2개가 있습니다. 바로 여기서 확실히 짚고 넘어가야 하는 부분이 있습니다. 여기서는 Promise 분기라는 개념이 중요합니다.

Promise 분기에 대해 자세히 살펴보겠습니다. 아래 다이어그램이 이 상황을 설명합니다.

Promise

결과가 준비되면(Promise가 확인 또는 거부됨) .then().catch() 체인 2개가 모두 실행되어(맨 위 체인이 먼저 실행됨) 서로 간섭하지 않고 작업을 수행합니다. showComponentInPopup은 팝업을 숨기고 응용 프로그램 코드의 체인이 필요한 작업을 처리합니다.



대화 상자 함수 라이브러리


이제 showComponentInPopup 함수가 있으므로 이 함수를 사용하는 대화 상자 함수 라이브러리 구현을 살펴보겠습니다. 라이브러리는 정적 메서드와 함께 DialogService 클래스로 표현됩니다. 이 클래스는 app/dialog.service.ts 파일에 배치할 것입니다.


확인 대화 상자

확인 대화 상자는 사용자가 작업을 확인 또는 취소할 수 있는 버튼 2개(확인 및 취소)와 확인 텍스트가 포함된 대화 상자를 나타내는 기본 confirm 함수와 유사합니다. 여기서는 확인/취소 버튼을 사용하는 okCancelDialog와 예/아니요 버튼을 사용하는 yesNoDialog, 이렇게 두 가지 다른 함수를 구현할 것입니다. 확인 텍스트는 함수의 매개 변수로 전달됩니다. 대화 상자 함수를 만드는 프로세스의 첫 번째 단계로 대화 상자 콘텐츠를 나타내는 컴포넌트를 구현합니다.

이 작업을 위해 코드가 다음과 같은 OkCancelCmp 컴포넌트를 만듭니다.

// OkCancelCmp component implements content of the Dialogs.yesNoDialog dialog.
@Component({
selector: 'ok-cancel-cmp',
template:
  `<div style="padding:10px 10px">
     
    <br/>
    <br/>
    <div>
      <button (click)="clicked(true)"></button>
      <button (click)="clicked(false)"></button>
    </div>
  </div>`
})
export class OkCancelCmp implements IPromiseResult {
question: string;
okCaption = 'Ok';
cancelCaption = 'Cancel';
private _result: Promise<any>;
private _resolve: any;
private _reject: any;
​
constructor() {
  this._result = new Promise((resolve, reject) => {
    this._resolve = resolve;
    this._reject = reject;
  });
}
​
get result(): Promise<any> {
  return this._result;
}
​
clicked(ok: boolean) {
  if (ok) {
    this._resolve();
  } else {
    this._reject();
  }
}
}


확인 텍스트와 버튼 캡션은 질문, okCaption, cancelCaption 속성으로 표현됩니다.(뒤의 두 가지 속성은 기본적으로 '확인'과 '취소'로 할당됩니다. 해당 속성은 다른 값을 할당하여 변경할 수 있습니다. IPromiseResult 인터페이스로 표현되는 계약에 따른 대화 상자 결과는 Promise 유형의 result 속성으로 노출됩니다. 이 대화 상자 결과는 사용자가 누른 버튼에 따라 두 가지 상태(확인됨 또는 취소됨)만 가정하기 때문에 확인은 확인된 Promise로, 취소는 거부된 Promise로 간주하는 것이 편합니다.

이 대화 상자를 사용하는 응용 프로그램은 다음과 비슷합니다.

okCancelDialog('Do this?').then(okDelegate).catch(cancelDelegate);


okDelegate 함수는 사용자가 확인 버튼을 누르면 호출되고 cancelDelegate는 취소 버튼을 누르면 호출됩니다. 컴포넌트 생성자에서 result 속성에 저장되는 Promise를 만듭니다.

constructor() {
this._result = new Promise((resolve, reject) => {
  this._resolve = resolve;
  this._reject = reject;
});
}


Promise 생성자는 클라이언트 코드가 .then() 및 .catch() 호출에서 지정한 콜백 함수에 대한 참조를 수신하는 resolve 및 reject 매개 변수 2개와 함께 함수를 수락합니다. 즉, 위 예에서 okDelegate는 resolve 매개 변수 값으로, cancelDelegate는 reject 매개 변수 값으로 전달됩니다. Promise 객체 공급자의 할 일은 다음과 같습니다.

  • Promise 결과가 준비되면(즉, 사용자가 확인 버튼을 누르면) resolve 호출. 그러면 .then() 호출에서 클라이언트 코드가 전달한 delegate가 실행됩니다.

  • Promise가 거부되면(즉, 사용자가 취소 버튼을 누르면) reject 호출. 그러면 .catch() 호출에서 클라이언트 코드가 전달한 delegate가 실행됩니다.

이 작업을 위해 컴포넌트의 비공개 속성(각각 _resolve 및 _reject)에 resolve 및 reject 매개 변수를 저장합니다.

그런 다음 아래와 같이 템플릿의 버튼에 바인딩되는 클릭 이벤트 처리기 메서드를 추가합니다.

<button (click)="clicked(true)"></button>
<button (click)="clicked(false)"></button>


이 메서드에서는 전달된 매개 변수 값에 따라 _resolve 또는 _reject를 호출합니다.

clicked(ok: boolean) {
if(ok) {
  this._resolve();
} else {
  this._reject();
}
}


다 끝났습니다! 대화 상자 콘텐츠 컴포넌트 구현을 마쳤습니다. 이제 대화 상자 함수를 쉽게 추가할 수 있습니다.

static okCancelDialog(question: string, vcr: ViewContainerRef, cmpResolver: ComponentFactoryResolver): Promise<any> {
return showComponentInPopup({}, OkCancelCmp, { question: question }, vcr, cmpResolver);
}


showComponentInPopup을 호출하고 콘텐츠 컴포넌트 유형(OkCancelCmp)을 매개 변수로 전달합니다. 또한 컴포넌트 속성 값도 전달하는데, 이 경우에는 질문 속성만 전달합니다. 이러한 속성의 값은 동일하게 명명된 함수 매개 변수에서 수신됩니다.

{ question: question }


그리고 위에서 설명한 ViewContainerRefComponentFactoryResolver 객체를 전달합니다. 해당 객체는 함수 매개 변수로 수신됩니다.

static yesNoDialog(question: string, vcr: ViewContainerRef, cmpResolver: ComponentFactoryResolver): Promise<any> {
return showComponentInPopup({}, OkCancelCmp, { question: question, okCaption: 'Yes', cancelCaption: 'No' }, vcr, cmpResolver);
}


이것은 여러 버튼 캡션(예, 아니요)이 있는 okCancelDialog 함수의 변형입니다. 여기서 유일한 차이점은 질문 속성 값 외에 버튼 캡션 값도 콘텐츠 컴포넌트에 전달한다는 것입니다.

{ question: question, okCaption: 'Yes', cancelCaption: 'No' },


라이브러리를 NgModule로 만들기

동적으로 만든 Angular 컴포넌트에는 해결해야 하는 미묘한 차이가 하나 있습니다. ViewContainerRef.createComponent 메서드로 만든 모든 컴포넌트는 NgModule의 entryComponents 메타데이터 속성에 추가해야 합니다. 이 요구 사항을 충족하기 위해 app/dialog.service.ts 파일에서 특수 DialogsModule 모듈을 만듭니다. 이 모듈은 대화 상자 함수 라이브러리에서 대화 상자 콘텐츠로 사용되는 모든 컴포넌트를 참조합니다. 정의는 다음과 같습니다.

@NgModule({
imports: [BrowserModule, WjInputModule],
declarations: [LoginCmp, OkCancelCmp],
entryComponents: [LoginCmp, OkCancelCmp],
})
export class DialogsModule {
}

이 NgModule이 있으면 라이브러리를 사용하는 모든 응용 프로그램 모듈이 NgModule 정의에서 DialogsModule을 가져와야 합니다.


응용 프로그램에서 확인 대화 상자 함수 사용

app/data.service.ts 파일에서 만든 항목을 사용하여 app.component.ts 파일 내에서 Promise 기반 대화 상자를 구현할 것입니다. 먼저, 서비스를 AppModule로 가져와야 합니다.

import { Component, ComponentFactoryResolver, Inject, ViewContainerRef } from '@angular/core';
import { DialogService } from './dialog.service';
​
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
...
}


그런 다음 위에서 설명한 것처럼 ViewContainerRefComponentFactoryResolver Angular 서비스에 대한 참조를 얻어야 합니다. 해당 참조는 컴포넌트의 생성자 매개 변수에 삽입하여 얻을 수 있습니다.

constructor(@Inject(ViewContainerRef) private _vcr: ViewContainerRef, @Inject(ComponentFactoryResolver) private _cmpResolver: ComponentFactoryResolver) {}


이제 다음과 같이 사용할 수 있습니다.

yesNoDialog() {
DialogService.yesNoDialog('Do you really want it?', this._vcr, this._cmpResolver).then(() => alert(`You answered YES`)).catch(() => alert(`You answered NO`));
}


이 호출은 사용자가 예 버튼을 누른 경우 "You answered YES"(예라고 답변하셨습니다)라는 알림을, 아니요 버튼을 누른 경우에는 "You answered NO"(아니요라고 답변하셨습니다)라는 알림을 표시합니다.

okCancelDialog() {
DialogService.yesNoDialog('Do you confirm this action?', this._vcr, this._cmpResolver).then(() => alert(`You confirmed the action`)).catch(() => alert(`You cancelled the action`));
}


이 호출은 사용자가 확인 버튼을 누른 경우 "You confirmed the action"(작업을 확인하셨습니다)라는 알림을, 취소 버튼을 누른 경우에는 "You cancelled the action"(작업을 취소하셨습니다)라는 알림을 표시합니다.


로그인 대화 상자 시뮬레이터

간단하게 설명하기 위해 이 로그인 대화 상자 구현은 완벽하게 작동하지 않습니다. 대화 상자에서 확인 버튼을 누르면 대화 상자가 서버에 요청을 보내고, 인증 결과(성공 또는 실패)에 따라 대화 상자 결과를 나타내는 Promise를 확인 또는 거부하는 핵심 기능을 갖춘 로그인 대화 상자의 시뮬레이션일 뿐입니다.

로그인 시뮬레이터 대화 상자에는 성공과 실패를 시뮬레이션하는 버튼이 2개 있습니다. 대화 상자의 콘텐츠는 다음과 같이 구현되는 LoginCmp 컴포넌트로 나타납니다.

@Component({
selector: 'login-cmp',
template:
  `<div style="padding:10px 10px">
    <b>Login Dialog</b>
    <br/>
    <br/>
    <button (click)="simulate(true)">Simulate Success</button>
    <br/>
    <br/>
    <button (click)="simulate(false)">Simulate Failure</button>
  </div>`
})
export class LoginCmp implements IPromiseResult {
private _result: Promise<any>;
onResult = new EventEmitter();
​
constructor() {
  this._result = new Promise((resolve, reject) => {
    this.onResult.subscribe((success) => {
      if (success) {
        resolve('Done');
      } else {
        reject('Access denied');
      }
    });
  });
}
​
get result(): Promise<any> {
  return this._result;
}
​
simulate(success: boolean) {
  setTimeout(() => {
    this.onResult.next(success);
  }, 0);
}
}


여기서는 결과 promise를 확인 또는 거부하기 위해 로그인 대화 상자에서 여러 기법을 사용합니다. 컴포넌트가 onResult 이벤트를 선언합니다.

onResult = new EventEmiter();


이 이벤트는 서버에서 인증 결과를 수신한 후 트리거됩니다. 이벤트 값은 인증 결과(이 경우에는 성공/실패 부울 값)를 유지합니다. 이 이벤트는 시뮬레이션 메서드로 트리거되고, 서버와의 비동기식 통신을 시뮬레이션하는 시간 제한이 있습니다. 결과 Promise는 생성자에서 생성되고 Promise 콜백 함수는 onResult 이벤트를 구독하고 이벤트 데이터 값에 따라 결과를 확인 또는 거부합니다. Promise는 성공("완료" 문자열)이면 확인되고 오류("액세스 거부")가 발생하면 거부되는데, 대화 상자를 호출하는 코드로 검사할 수 있습니다. 콘텐츠 컴포넌트가 완료되고 마지막 단계로 대화 상자 함수 loginDialog를 만듭니다.

static loginDialog(anchor: HTMLElement, vcr: ViewContainerRef, cmpResolver: ComponentFactoryResolver): Promise<any> {
return showComponentInPopup({ owner: anchor }, LoginCmp, {}, vcr, cmpResolver);
}


화면 가운데 대화 상자를 표시하는 okCancelDialog 함수와 반대로 loginDialog는 예를 들어, 대화 상자를 트리거하는 버튼과 같은 일부 요소에 시각적으로 고정하여 표시하려고 합니다. 해당 요소는 앵커 매개 변수에서 지정할 수 있으며, 이 요소는 Popup 옵션 개체를 showComponentInPopup 함수의 첫 번째 매개 변수로 전달하여 Popup의 소유자 속성에 할당합니다.

{ owner: anchor }


이제 응용 프로그램에서 이 함수를 사용할 수 있습니다.

HTML:
<button #button1 (click)="loginDialog(button1)">
Login
</button>
​
Event Handler:
loginDialog(owner: HTMLElement) {
DialogService.loginDialog(owner, this._vcr, this._cmpResolver).then((data) => alert(`Logged in! Status: ${data}`)).catch((error) => alert(`Login failed. Error: ${error}`));
}


button1 요소를 대화 상자의 소유자로 지정합니다. 따라서 대화 상자가 화면 가운데 표시되지 않고 해당 버튼에 시각적으로 고정되어 나타납니다. .then() 처리기 함수는 확인된 Promise 데이터를 저장하는 데이터 매개 변수를 사용하고, .catch() 처리기 함수는 거부된 Promise에 대한 오류 정보를 포함하는 오류 매개 변수를 사용합니다.


모달 대화 상자 구현

이 포스팅에서는 임의의 Angular 컴포넌트에 의해 콘텐츠와 동작이 정의되고 대화 상자 결과가 Promise 객체로 나타나는 함수 호출로 표시되는 모달 대화 상자를 구현하는 방법에 대해 설명했습니다.

대화 상자를 표시하기 위한 도구로 Wijmo의 Popup 컨트롤을 사용했습니다.


지금 바로 Wijmo 무료 체험판을 다운로드 하여 직접 확인해 보세요!

baa420b8e8ddf9cb9df1e575a60b6f54_1623115182_5968.png
 

  • 페이스북으로 공유
  • 트위터로  공유
  • 구글플러스로 공유
  • 카카오톡으로 보내기

댓글목록

등록된 댓글이 없습니다.

그레이프시티 홈페이지를 통해 제품에 대해서 더 자세히 알아 보세요!
홈페이지 바로가기

태그

인기글

더보기
  • 인기 게시물이 없습니다.
그레이프시티 홈페이지를 통해 제품에 대해서 더 자세히 알아 보세요!
홈페이지 바로가기
이메일 : sales-kor@grapecity.com | 전화 : 1670-0583 | 경기도 안양시 동안구 시민대로 230, B-703(관양동, 아크로타워) 그레이프시티(주) 대표자 : 허경명 | 사업자등록번호 : 123-84-00981 | 통신판매업신고번호 : 2013-경기안양-00331 Copyright ⓒ 2021 GrapeCity inc.