Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Showing a custom form. #126

Closed
vivekimsit opened this issue Jul 1, 2016 · 19 comments
Closed

Showing a custom form. #126

vivekimsit opened this issue Jul 1, 2016 · 19 comments

Comments

@vivekimsit
Copy link

  • I'm submitting a ...

[ ] feature request

Is there a possibility to show custom form in the dialog?

@paulbakker
Copy link

paulbakker commented Jul 7, 2016

I'm struggling with the same question. Based on the code you linked above I almost got it working. I'm using the Vex plugin though, and my dialog shows up without any style (it's in the upper left corner, no backdrop, no border etc.). I'm clearly missing styles, but I'm not sure what should be set. All Vex examples are using the builder that takes care of this.

Very nice mechanism for advanced dialogs btw!

this.modal.open(FlightControlDialog, new FlightControlDialogData("test")).then(p => {
        p.result.then(r => {
          console.log(r);

        });
      })
import {    
    Component,
    ViewEncapsulation
} from '@angular/core';

import {ModalComponent, DialogRef} from 'angular2-modal';
import {BSModalContext} from 'angular2-modal/plugins/bootstrap/index';


import {
    DialogPreset,
    VEXDialogButtons
} from 'angular2-modal/plugins/vex/index';

export class FlightControlDialogData extends BSModalContext {
    constructor(public flightcontrol : any) {
        super();
    }
}


@Component({
    selector: 'modal-content',
    directives: [VEXDialogButtons],
    encapsulation: ViewEncapsulation.None,
    template:
        `<div class="vex-dialog-message">{{context.message}}</div>
    <div class="vex-dialog-input">
        <input name="vex" 
               type="text" 
               class="vex-dialog-prompt-input"
               [(ngModel)]="context.defaultResult" 
               placeholder="{{context.placeholder}}">
    </div>`
})

export class FlightControlDialog implements ModalComponent<FlightControlDialogData>  {
    private context: FlightControlDialogData;

   constructor(public dialog: DialogRef<FlightControlDialogData>) {
        this.context = dialog.context;
    }
}

What am I missing?

@shlomiassaf
Copy link
Owner

First, unrelated to the issue:

export class FlightControlDialogData extends BSModalContext {
    constructor(public flightcontrol : any) {
        super();
    }
}

You extend the BSModalContext which is from the Bootstrap plugin, no need for that its not the same data structure.

As for the issue, the CSS theme files are not included in the plugin.
This is similar to bootstrap plugin, which requires you to use the bootstrap CSS.

It's a common practice in such cases.
Just add it in the head or at app root.

@paulbakker
Copy link

paulbakker commented Jul 7, 2016

Thanks for the very quick reply!
Simple dialogs, created using the builder interface, look correct. So I think the styles are available.
Is there an example of this scenario with Vex?

@shlomiassaf
Copy link
Owner

If you are using the open() method you need to supply a component that have the right html elements.

Your directive is missing some container elements, for example the root element should be a form.

Check the components inside the plugin source code

@shlomiassaf
Copy link
Owner

Your html need to comply with vex html

@paulbakker
Copy link

Thanks for the hints @shlomiassaf, I got it to render correctly. There's a few details to know that are not straight forward to guess from the existing examples and docs. An example would be a very useful addition I think. In the mean time for others looking for the same, this is the code I ended up with.

import {    
    Component,
    ViewEncapsulation
} from '@angular/core';

import {ModalComponent, DialogRef} from 'angular2-modal';
import {VEXModalContext} from 'angular2-modal/plugins/vex/index';


import {
    DialogPreset,
    VEXDialogButtons
} from 'angular2-modal/plugins/vex/index';

export class FlightControlDialogData extends VEXModalContext {
    constructor(public flightcontrol : any) {
        super();
        this.className = "default";
        this.contentClassName = "vex-content";
        this.overlayClassName = "vex-overlay";

    }
}


@Component({
    selector: 'flightcontrol',
    directives: [VEXDialogButtons],
    encapsulation: ViewEncapsulation.None,
    template: require('./flightcontrol.dialog.html')      
})

export class FlightControlDialog implements ModalComponent<FlightControlDialogData>  {
    private context: FlightControlDialogData;

   constructor(public dialog: DialogRef<FlightControlDialogData>) {
        this.context = dialog.context;
    }
}
<form class="vex-dialog-form">
    <div class="vex-dialog-message">MY TEST!!!! {{context.message}}</div>
    <div class="vex-dialog-input">
        <input name="vex" type="text" class="vex-dialog-prompt-input" [(ngModel)]="context.defaultResult" placeholder="{{context.placeholder}}">
    </div>
</form>
this.modal.open(FlightControlDialog, new FlightControlDialogData("test")).then(p => {
        p.result.then(r => {
          console.log(r);

        });
      })

@paulbakker
Copy link

After upgrading to Angular 2 rc5 I'm running in an issue with Vex custom dialogs.
Based on the code above (that worked previously) I'm now getting:

zone.js:484 Unhandled Promise rejection: Cannot read property 'inElement' of undefined ; Zone: angular ; Task: HTMLButtonElement.addEventListener:click ; Value: TypeError: Cannot read property 'inElement' of undefined(…) TypeError: Cannot read property 'inElement' of undefined
    at Overlay.createOverlay (http://localhost:3000/main.bundle.js:26897:45)
    at http://localhost:3000/main.bundle.js:26890:48
    at Array.map (native)
    at Overlay.open (http://localhost:3000/main.bundle.js:26890:15)
    at Modal.open (http://localhost:3000/main.bundle.js:27075:41)
    at Home.openAlert (http://localhost:3000/main.bundle.js:27597:21)
    at DebugAppView._View_Home5._handle_click_9_0 (Home.ngfactory.js:1909:35)

To upgrade I did the following:

  • Register my dialog as a entryComponent entryComponents: [ ServiceDialog ] in the module definition
  • Set the overlay viewcontainer: overlay.defaultViewContainer = vcRef in the component that opens the dialog.

Note that default dialogs do work correctly after the update.

@shlomiassaf
Copy link
Owner

@paulbakker

In beta11 you don't need to the set defaultViewContainer in the code, just set it in the root component template, see this example

As for the error, in beta 11 its a lot easier to open custom modals.
It's hard for me to track down the specific error you have but I think that you are calling open with the wrong parameters. The 2nd parameter is of type OverlayConfig and not the context.

I'll use an example:

// import ......
import { overlayConfigFactory } from "angular2-modal";

@Component({...})
class CutomModal{ }

this.modal.open(CustomModal, overlayConfigFactory({ num1: 2, num2: 3 }, BSModalContext));

{ num1: 2, num2: 3 } is the actual context that will be on DialogRef.context
BSModalContext is the context class to init (new).

In this sample I used it so it will load all of the default context properties used in the bootstrap plugin.

If you don't supply it the default OverlayContext is used.

In your example, it should be:

this.modal.open(CustomModal, overlayConfigFactory({ }, FlightControlDialogData) /* returns OverlayConfig */ );

Or, since there isn't any logic in FlightControlDialogData:

this.modal.open(CustomModal, overlayConfigFactory({ 
   className: "default",
   contentClassName: "vex-content",
   overlayClassName: "vex-overlay"
}, VEXModalContext));

Note that overlayConfigFactory is for on-the-fly use as it skips the need for a builder, if you want to supply a fluent API you will have to use the builder as before. However now you have the 'toOverlayConfig()` method on the builder. It doesn't seem like the use case you need to I want elaborate on that.

@paulbakker
Copy link

Thanks for the reply!
I'm trying to upgrade to beta11 to test this out, but I'm running in a EXCEPTION: No provider for Renderer!. Module definition currently looks like this (based on the demo app). Just showing the Modal related parts:

@NgModule({
  declarations: [APP_COMPONENTS],
  bootstrap: [App],
  imports: [
    ModalModule.forRoot(),
    VexModalModule
  ],
  providers: [

    VexModalModule.getProviders()
  ],

  //entryComponents: [ ServiceDialog ]
})

@shlomiassaf
Copy link
Owner

You don't need VexModalModule.getProviders() since the providers are set in the imports of VexModalModule.

The getProviders() is used when you want to have multiple plugins in the same project, which is the case in the demo app.

Try removing it, i'm not sure its the issue but let's see.

@paulbakker
Copy link

Without the VexModalModule.getProviders() I missing another provider: ORIGINAL EXCEPTION: No provider for Renderer!

@shlomiassaf
Copy link
Owner

Are you using a systemJS based project (angular2-sees)? if so probably linked to #174

@paulbakker
Copy link

I'm using Webpack, but that's mentioned in #174 as well.

@paulbakker
Copy link

So I continued testing now that beta12 seems to work.

I've tried several ways (based on the examples) of creating the custom dialog, but always getting polyfills.bundle.js:14847 Uncaught TypeError: Cannot set property stack of [object Object] which has only a getter

For example, this is one of the tries.

openAlert(service) {

    new DialogPresetBuilder<DialogPreset>(this.modal)
            .className(this.theme)
            .content(ServiceDialog)
            .message('Ary you coming to the event?')
            .addOkButton('Yep!')                        
            .open();

  }


@Component({
  selector: 'servicehealth',
  encapsulation: ViewEncapsulation.None,
  template: require('./service.dialog.html')
})

export class ServiceDialog implements ModalComponent<DialogPreset> {
  private context: DialogPreset;

  constructor(public dialog: DialogRef<DialogPreset>) {
    this.context = dialog.context;
  }
}

@JulioC
Copy link

JulioC commented Sep 21, 2016

As probably figured out here, the error "Cannot read property 'inElement' of undefined" happens only when you try to load a modal without passing a context object.

Line where the error comes from: https://github.com/shlomiassaf/angular2-modal/blob/8d0c9320233c7c746a2702346060a8806f2ba3a7/src/components/angular2-modal/overlay/overlay.service.ts#L87

For anyone else looking for the solution, check PR #194

@JulioC
Copy link

JulioC commented Sep 21, 2016

@paulbakker "Cannot set property stack of [object Object]..." is an error already fixed on Angular exception handling, but it hides the original error. Place a breakpoint on the line it happens and check the stack for the original exception.

@paulbakker
Copy link

Updated to beta13, and after some changes got everything to work. I didn't open this issue originally, but I think it can be closed.
I do think the docs/demos could use some love, it's (at least to me) not immediately obvious how to work with the context etc.

@shlomiassaf
Copy link
Owner

closing, reopen if needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants