Angular2 Service可以创建,显示和管理其内部组件?如何实现js alert()? [英] Angular2 Service which create, show and manage it's inner Component? How to implement js alert()?

查看:65
本文介绍了Angular2 Service可以创建,显示和管理其内部组件?如何实现js alert()?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图找到一种在服务中拥有和管理angular2组件的方法,但没有成功:

I tried to find a way for having and manage an angular2 Component in a Service but with no success:

  1. 我需要创建:

  1. I need to create:

AlertService{

    alertConfirm(msg): Promise;
}

alertConfirm将显示​​一个带有2个按钮(确定,取消)的确认"窗口,并返回用户的选择作为承诺.

alertConfirm will prompt an Confirmation window with 2 buttons (Ok, Cancel) and will return users' choise as a Promise.

  1. 通常,此想法是实现著名的JavaScript alert()方法 但具有设计好的UI窗口和取消按钮.
  1. In General, the idea is to implement the famous JavaScript alert() method but with a designed UI window and with also a cancel button.

该方法将返回Promise并带有用户选择的响应:确定"或取消".

The method will return a Promise with a response of user's choice: "OK" or "Cancel".

  1. 我试图找到一种在AlertService中保存匿名"组件AlertComponent的方法:

  1. I tried to find a way for holding an "anonymous" component, AlertComponent, in AlertService:

AlertComponent{

    showMsgConfirm(msg): Promise;
}

当用户关闭提示窗口或单击确定"或取消"时,Promise将设置为带有响应.

The Promise will be set with a response when user close prompt window or click "OK" or "Cancel".

  1. 问题:

如何使"AlertService"具有内部的"AlertComponent",可以通过其"alertOK"方法进行管理?

How to make "AlertService" to have an inner "AlertComponent" which can be managed by it's "alertOK" method?

我的意思是,我没有找到让"alertConfirm"调用"showMsgConfirm"方法并返回其Promise作为响应的方法.

I mean, I didn't find a way for "alertConfirm" to call "showMsgConfirm" method and to return it's Promise as a response.

例如,从主要应用组件调用:

for example, calling from main app component:

this.alertService.alertConfirm("Save changes?").then(res => {
    if(res.ok){console.log("Can be saved");
}, err=> { });

对此有什么想法吗?

谢谢

更新:2种不同的解决方案,但没有成功管理AlertComponent的方法:

Update:2 different ideas for solution, but with no sucess to manage the AlertComponent:

import { Injectable, ViewContainerRef, ReflectiveInjector, ComponentFactoryResolver, ComponentRef } from '@angular/core';

import { AlertComponent } from './../components/modales/AlertComponent/AlertComponent.component';

@Injectable()
export class AlertService {

    constructor(private componentFactoryResolver: ComponentFactoryResolver) { }

    public createAlertComp(vCref: ViewContainerRef): ComponentRef<any> {


        let factory = this.componentFactoryResolver.resolveComponentFactory(AlertComponent);

        /*

        //Option 1:

        // vCref is needed cause of that injector..
        let injector = ReflectiveInjector.fromResolvedProviders([], vCref.parentInjector);

        // create component without adding it directly to the DOM
        let comp = factory.create(injector);

        // add inputs first !! otherwise component/template crashes ..
        comp.instance.model = modelInput;

        // all inputs set? add it to the DOM ..
        vCref.insert(comp.hostView);

        return comp;
        */

        //Option 2:

        var componentRef: ComponentRef<AlertComponent> = vCref.createComponent(factory);       
        return null;
    }


}

推荐答案

答案是...:

  • 服务:

  1. _counter 用于每个模态具有唯一的名称.
  2. comp.instance.close 是用于订阅EventEmitter的内部组件的属性.
  1. _counter is used for each modal to have a unique name.
  2. comp.instance.close is a property of inner component for subscribing for EventEmitter.

.

import { Injectable, ViewContainerRef, ReflectiveInjector, ComponentFactoryResolver, ComponentRef, EventEmitter } from '@angular/core';

import { CtmAlertComponent } from './ctmAlert/ctmAlert.component';


@Injectable()
export class AlertCtmService {

    private _vcr: ViewContainerRef;
    private _counter: number = 0;

    constructor(private componentFactoryResolver: ComponentFactoryResolver, public viewRef: ViewContainerRef) {
        console.log("AlertCtmService.constructor:");

        //TODO: Consider appending to this.viewRef: "#alertCtmServiceContainer" as a Dom elemnt perent container which will hold all AlertModals:
        // Maybe by: 
        // this.viewRef.element.nativeElement.insertAdjacentHTML('beforeend', '<div class="alertCtmServiceContainer"></div>');

        this._vcr = this.viewRef;
    }

    public alertOK(alertMsg: string): EventEmitter<any> {
        return this.createEventEmitterComponent("CtmAlertComponent", alertMsg, false);
    }

    public alertConfirm(alertMsg: string): EventEmitter<any> {
        return this.createEventEmitterComponent("CtmAlertComponent", alertMsg, true);
    }

    private createEventEmitterComponent(componentName: string, alertMsg: string, isConfirm: boolean): EventEmitter<any> {

        console.log("AlertCtmService.createEventEmitterComponent:");

        switch (componentName) {
            case "CtmAlertComponent":
            default:
                var _component = CtmAlertComponent;
                break;
        }

        let factory = this.componentFactoryResolver.resolveComponentFactory(_component);

        // vCref is needed cause of that injector..
        let injector = ReflectiveInjector.fromResolvedProviders([], this._vcr.parentInjector);

        // create component without adding it directly to the DOM
        let comp = factory.create(injector);

        // add inputs first !! otherwise component/template crashes ..
        comp.instance.close.subscribe(resp => {
            console.log("AlertCtmService.createEventEmitterComponent: comp.instance.close.subscribe: resp=" + resp.ok);
            comp.destroy();
        })

        comp.instance.alertBodyMsg = alertMsg;
        comp.instance.isConfirm = isConfirm;
        comp.instance.nameId = "Modal" +(++this._counter).toString();

        // all inputs set? add it to the DOM ..
        this._vcr.insert(comp.hostView);

        //return null;
        return comp.instance.close;

    }

    public init(vCref: ViewContainerRef): ViewContainerRef {
        this._vcr = vCref;
        return this._vcr;
    }

}

  • 内部组件:

    1. 使用 Bootstrap 处理UI中 Modal 的显示:modal('show')\ modal('hide').
    1. Using Bootstrap for handling display of Modal in UI: modal('show') \ modal('hide').

  • .

    import { Component, AfterViewInit, Input, ViewChild, ElementRef, Renderer, NgZone, EventEmitter} from '@angular/core';
    
    @Component({
        selector: 'ctm-alert',
        styles: [``],
        templateUrl: '/app/shared/alertCtm/ctmAlert/CtmAlert.component.html',
        styleUrls: ['./app/shared/alertCtm/ctmAlert/CtmAlert.component.css'],
        providers: []
    })
    
    export class CtmAlertComponent implements AfterViewInit {
    
        public ModalIsVisible: boolean;
    
        //private static subscriptions: Object = {};
    
        //enums = Enums;
    
        close = new EventEmitter();
        public nameId = "";
        private isOk = false;
        alertBodyMsg: string = "";
        isConfirm = false;
    
        constructor() {
            console.log("CtmAlertComponent.constructor:");
        }
    
        ngAfterViewInit() {
            this.showModal();
    
            var attrId = this.getIdAttr();
            $('#' + attrId).on('hidden.bs.modal', function () {
                debugger;
                console.log('CtmAlertComponent: #licenseModal_XXX.on(hidden.bs.modal)');
                this.submitStatus();
            }.bind(this) );
    
        }
    
        showModal() {        
            this.ModalIsVisible = true;
            var attrId = '#' +this.getIdAttr();
            $(attrId).modal('show');
        }
    
        hideModal() {
            this.ModalIsVisible = false;
            var attrId = '#' + this.getIdAttr();
            $(attrId).modal('hide');
        }
    
    
    
        getIdAttr(): string {
            return "ctmAlertModal_" + this.nameId;
        }
    
        submitStatus() {
            var resp = { ok: (this.isOk == true) };
            this.close.emit(resp);
    
        }
        submitOk() {
            this.isOk = true;
            this.hideModal();
        }
        submitCancel() {
            this.isOk = false;
            this.hideModal();
        }
    
    
    }
    

    • 应用声明:

      1. 不幸的是,我们必须在main-app模块中声明匿名组件.
      2. 我们必须添加entryComponents的声明:[CtmAlertComponent],
      1. unfortunately, we must declare the anonymus component in our main-app module.
      2. We must add a declaration of entryComponents: [CtmAlertComponent],

    • .

      import { CtmAlertComponent } from './shared/alertCtm/ctmAlert/ctmAlert.component';
      
      @NgModule({
        imports: [
          BrowserModule,
          HttpModule,    
          AppRoutingModule,
      ...
        ],
        declarations: [
            CtmAlertComponent,
            AppComponent,
      ...
        ],
        entryComponents: [CtmAlertComponent],
        providers: [
      ...
        ],
        bootstrap: [AppComponent],
      })
      export class AppModule { }
      
      enableProdMode();
      

      • 模式用户界面:

        1. 此html模板基于引导程序的UI:

      • .

        <div class="ctmAlertModal modal fade in" [id]="getIdAttr()" role="dialog">
            <div class="modal-dialog modal-lg" [ngClass]="{'modal-lg-6': true }">
        
                <!-- Modal content-->
                <div class="modal-content">
        
                    <div class="modal-header" style="">
                        <div class="pull-right" style="position: relative;">
                            <a href="#" data-dismiss="modal" (click)="hideModal()"><span class="fa fa-times-circle" aria-hidden="true" style="color: #949494"></span></a>
                        </div>
                    </div>                   
        
                    <div class="modal-body">
        
                        <div class="modal-body-msg">
                            {{alertBodyMsg}}
                        </div>
        
        
                        <div class="modal-body-buttons">
        
                            <div style="margin: 0 auto;" [style.width]="(isConfirm)? '165px' : '70px' ">
        
                                <button type="button" *ngIf="isConfirm" class="btn-submit pull-left btn-cancel" [ngClass]="{'disabled': false }" [disabled]="false" (click)="submitCancel()">
                                    <!--<img alt="End-Training" class="centering-me2" src="../../../contents/training_state_stop_white.svg">-->
                                    Cancel
                                </button>
                                <button type="button" class="btn-submit pull-right" [ngClass]="{'disabled': false }" [disabled]="false" (click)="submitOk()">
                                    <!--<img alt="Resume-Training" src="../../../contents/training_state_play_white.svg">-->
                                    OK
                                </button>
                            </div>
        
        
                        </div>
        
        
                    </div>
        
                </div>
        
            </div>
        </div>
        

        .

        • 用法::

        1. 例如:

        .

            this.alertCtmService.alertOK("Save changes???").subscribe(function (resp) {
                console.log("alertCtmService.alertOK.subscribe: resp=" + resp.ok);
                this.saveData();
            }.bind(this) );
        

        **

        **

        来源:

        1. angular2-ngmodule

          这篇关于Angular2 Service可以创建,显示和管理其内部组件?如何实现js alert()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆