shlomiassaf / ngx-modialog

Modal / Dialog for Angular
http://shlomiassaf.github.io/ngx-modialog
MIT License
686 stars 242 forks source link

Integration angular2-modal in hybrid app (Angular1 + Angular2) #50

Open chandermani opened 8 years ago

chandermani commented 8 years ago

In a hybrid setup where Angular1 and Angular2 are both present, modal dialog service does not work. It fails to locate the root element (Angular2) reference, as none exists.

This is the culprit line in modal.ts

let elementRef: ElementRef = (<any>this.appRef)._rootComponents[0].location;

The workaround that i have used it to create a Angular2 component that encompasses the complete Angular1 app and store its reference in a global export.

While this approach works with standard modal dialog, it fails to work with custom dialog component as it does not take a parameter. to specify ElementRef to attach the dialog to.

I have extended the open method in modal.ts for the time being to make custom modal dialog work.

public open(componentType: FunctionConstructor, bindings: ResolvedProvider[],
                config?: ModalConfig, **inside?: ElementRef**): Promise<ModalDialogInstance> {
        // TODO: appRef.injector.get(APP_COMPONENT) Doesn't work.
        // When it does replace with the hack below.
        //let myElementRef = this.appRef.injector.get(APP_COMPONENT).location;
       **let elementRef: ElementRef = inside || (<any>this.appRef)._rootComponents[0].location;**

        return this.openInside(componentType, elementRef, null, bindings, config);
    }

Is this the right approach, or can someone suggest a better method to integrate angular2-modal in a hybrid app.

shlomiassaf commented 8 years ago

I didn't try the app with ngUpgrade...

I need some information about why it happens, what is the reason, so we can address that the right way.

chandermani commented 8 years ago

It happens because in a hybrid app, which has both Angular1 and Angular2, there is no root component. The root is Angular1.

I did some html reorganization so that there is a component is parent to most of the Angular1 view. Then track that component through global variable.

Since the custom component modal API does not take a ElementRef like other dialogs do, i updated the open method.

iradovanovic commented 8 years ago

Did you try to add providers (in/on boot.ts):

import {MODAL_BROWSER_PROVIDERS} from 'angular2-modal/platform-browser';
import {Modal} from 'angular2-modal';

upgradeAdapter.addProvider(MODAL_BROWSER_PROVIDERS);
upgradeAdapter.addProvider(Modal);

and also you have to use dialog from component.

import {Component, ViewContainerRef} from '@angular/core';
import {Modal} from 'angular2-modal';
import {BS_MODAL_PROVIDERS} from 'angular2-modal/plugins/bootstrap';

@Component({
    selector: 'xxx-component',
    templateUrl: './cmp.html',
    viewProviders: [ ...BS_MODAL_PROVIDERS ]
})
export class XxxComponent{

    constructor(private modal:Modal, viewContainer: ViewContainerRef) {
        modal.defaultViewContainer = viewContainer;
    }

    openDialog() {
        //noinspection TypeScriptUnresolvedFunction
        return this.modal.alert()
            .titleHtml('test')
            .open();
    }
}
jFensch commented 8 years ago

I have the modal working in a hybrid app using the methodology @iradovanovic describes.