2017-07-26 153 views
1

即時創建一個全球模態組件。 我的問題是,當我調用基於模態的號碼被調用的多次調用的訂閱方法。 如何防止可觀察訂閱方法的多個調用?請檢查我的代碼如下。提前致謝。Angular 4訂閱方法調用多次

modal.model.ts

export class Modal { 
    title: string; 
    message: string; 
    visible: boolean = false; 
} 

modal.service

import { Injectable } from '@angular/core'; 
import { Modal } from './modal.model'; 
import { Observable } from 'rxjs'; 
import { Subject } from 'rxjs/Subject'; 

@Injectable() 
export class ModalService { 
    static readonly YES = 1; 
    static readonly NO = 0; 

    private modal = new Modal(); 
    private subject = new Subject<Modal>(); 
    private action = new Subject<number>(); 

    confirmationDialog(message) { 
    this.modal.title = 'Confirmation'; 
    this.modal.message = message; 
    return this; 
    } 

    show() { 
    this.modal.visible = true; 
    this.setModal(this.modal); 
    return this; 
    } 

    setAction(action: number) { 
    this.action.next(<number>action); 
    } 

    getAction(): Observable<any> { 
    return this.action.asObservable(); 
    } 

    setModal(alert: Modal) { 
    this.subject.next(<Modal>alert); 
    return this; 
    } 

    getModal(): Observable<any> { 
    return this.subject.asObservable(); 
    } 
} 

modal.component

import { Component, OnInit } from '@angular/core'; 
import { ModalService } from './modal.service'; 
import { Modal } from './modal.model'; 

@Component({ 
    selector: 'modal', 
    templateUrl: './modal.component.html', 
    styleUrls: ['./modal.component.css'] 
}) 
export class ModalComponent implements OnInit { 
    public modal: Modal; 

    constructor(private modalService: ModalService){} 

    ngOnInit() { 
    this.modalService.getModal().subscribe((modal: Modal) => { 
     this.modal = modal; 
     console.log(modal); 
    }); 
    } 

    no() { 
    this.modalService.setAction(0); 
    this.modalService.close(); 
    } 

    yes() { 
    this.modalService.setAction(1); 
    this.modalService.close(); 
    } 
} 

調用模態分量

showModal() { 
    this.modalService.confirmationDialog('Are you sure you want to save this record?').show(); 
    this.modalService.getAction().subscribe(response => { 
    if(response === ModalService.NO) { 
     return; 
    } 
    console.log('call mutiple times'); 
    }); 
} 

這裏是關於控制檯日誌的輸出的屏幕截圖。 console log output

回答

2

我想我會更容易使用異步管你的模態分量內:

import { Component } from '@angular/core'; 
import { Observable } from 'rxjs'; 

import { ModalService } from './modal.service'; 
import { Modal } from './modal.model'; 

@Component({ 
    selector: 'modal', 
    templateUrl: './modal.component.html', 
    styleUrls: ['./modal.component.css'] 
}) 
export class ModalComponent { 
    public modal$: Observable<Modal>; 

    constructor(private modalService: ModalService){ 
     this.modal$ = this.modalService.getModal(); 
    } 

    no() { 
    this.modalService.setAction(0); 
    this.modalService.close(); 
    } 

    yes() { 
    this.modalService.setAction(1); 
    this.modalService.close(); 
    } 
} 

您的模板,裏面例如:

(modal$ | async)?.title 

這保證Angular正在清理組件銷燬本身的訂閱。

在創建模式時,您可以使用take運算符來完成訂閱,如果發送的x值完成訂閱。

this.modalService.getAction().take(1).subscribe(response => { 
    if(response === ModalService.NO) { 
     return; 
    } 
    console.log('call mutiple times'); 
}); 

我假設你只想要1個值(因爲它是一個簡單的對話框)。

+0

爲什麼我要拿不是功能錯誤? – Juan

+0

也許你的應用程序沒有導入所有的操作符,你可以通過導入運算符:'import'rxjs/add/operator/take';' – cyrix

+0

謝謝,你的代碼正在工作,take()方法取得了訣竅。但是,如果我點擊按鈕兩次,模式將彈出。任何想法? – Juan

-1

將您的訂閱移動到ctor。例如:

private unsubscribe: Subject<void> = new Subject<void>(); 

    constructor(private modalService: ModalService){ 
     this.modalService.getModal() 
      .takeUntil(this.unsubscribe) 
      .subscribe((modal: Modal) => { 
       this.modal = modal; 
       console.log(modal); 
     }); 
    } 

    ngOnInit() { 

    } 

    ngOnDestroy() { 
     this.unsubscribe.next(); 
     this.unsubscribe.complete(); 
    } 
+0

感謝您的建議,但仍然無法正常工作。 – Juan

+0

在ngOnDestroy lifecyclehook或通過'takeWhile'或'takeUntil'內部清除組件構造函數內部的訂閱是一種不好的做法。 – cyrix

+1

這是更多的解決他的多個訂閱射擊。無論如何,好點。更新。 – vidalsasoon