2017-07-26 109 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