flauc / angular2-notifications

A light and easy to use notifications library for Angular.
https://stackblitz.com/edit/angular2-notifications-example
MIT License
746 stars 164 forks source link

How to use the notification over modal popup #323

Open deepender87 opened 6 years ago

deepender87 commented 6 years ago

As per the steps mentioned in the notification example, I had set up it in my app component <simple-notifications [options]="notificationOptions" (onCreate)="onNotificationsCreate($event)" (onDestroy)="onNotificationsDestroy($event)" class="mm-alerts-popup"></simple-notifications>

Now it is showing the notification all over the places wherever it is required. Issue is I have specific page which has a form filling popup (modal) If i want to validate the data i am calling the notification service and showing the message. But as the "simple-notifications" component is at app level, it is showing below the popup/Modal. How i can achieve this? so that at this point i can show this over popup not at below of it.

flauc commented 6 years ago

you should be able to achieve this by simply setting a larger z-index on the notification. It's set to ViewEncapsulation.None so you should have no problem overriding it.

jeffmath commented 5 years ago

@flauc Setting a larger z-index does not work, because as #304 states, the modal layer is a direct child of the body element, whereas the notification is nested in a different child of the body element (namely, the app component), which has a lower z-index than the modal layer. Since the notification is nested, its higher z-index has no bearing on the display of the modal layer.

vishnu-dev commented 4 years ago

This still doesn't work in 2019. Any updates?

sapphous commented 4 years ago

This is indeed a most horrid conundrum. For anyone desperate for a hack to fix it, here's what I did: I created a service to inject components as children of body, then I used it in my App component. Credit to @caroso1222's post at https://hackernoon.com/angular-pro-tip-how-to-dynamically-create-components-in-body-ba200cc289e6 for saving me from a potentially long fight with Angular to try to get a component injected into the body effectively.

1) Create a service like this:

import { ApplicationRef, ComponentFactoryResolver, ComponentRef, EmbeddedViewRef, Injectable, Injector } from '@angular/core';

@Injectable()
export class BodyAdderService {

  constructor(
    private componentFactoryResolver: ComponentFactoryResolver,
    private appRef: ApplicationRef,
    private injector: Injector
  ) {
  }

  addToBody(component: any, instanceManipulations: any = null, domManipulations: any = null) {
    //grab component reference & attach it to the application
    const componentRef = this.componentFactoryResolver.resolveComponentFactory(component).create(this.injector);
    if(instanceManipulations)
      instanceManipulations(componentRef.instance);
    this.appRef.attachView(componentRef.hostView);

    //throw that dom boi into the body
    const domElem = (componentRef.hostView as EmbeddedViewRef<any>).rootNodes[0] as HTMLElement;
    if(domManipulations)
      domManipulations(domElem);
    document.body.appendChild(domElem);

    //to remove it again:
    //this.appRef.detachView(componentRef.hostView);
    //componentRef.destroy();
  }

}

2) In app.module.ts, do import { SimpleNotificationsComponent } from 'angular2-notifications'; and add entryComponents: [ SimpleNotificationsComponent ] to @NgModule. Obviously, import the service and add it to your providers as well.

3) In app.component.ts, again import SimpleNotificationsComponent and your service. Add your BodyAdderService to the constructor, e.g. construtor(..., private bodyAdder: BodyAdderService). In the constructor's body, add something like this (the example uses my BodyAdderService so it passes arrow functions to manipulate the component & the dom element, and passes in this.notificationOptions which is simply an angular2-notifications options hash, e.g. { timeOut: 3000, showProgressBar: true, ... }):

    this.bodyAdder.addToBody(SimpleNotificationsComponent, instance => {
      instance.options = this.notificationOptions;
    }, element => {
      element.style = "z-index:1200;"
    });

4) Take <simple-notifications></simple-notifications> out of your app's html template.

NOTES: You may not need the "options" bit, since in theory you can configure that globally in @NgModel. You may need to modify your z-index to fit your app: AFAIK modal dialogues are set to 1000 so 1200 is high enough, but I'm not sure. There's undoubtedly a better way to get that CSS in there, but CSS is the bane of my existence and after several attempts to get something working in app.component.scss I gave up and injected it inline into the DOM element. Anyone with a better solution for the CSS bit feel free to let me know.

@flauc It might be possible to roll some kind of dynamic injection like this into the repo without too much trouble, so that users can add something to their component's constructor, rather than adding the <simple-notifications> tag to their html template, to get body injection. I have too many uncertainties about how to do that well to try to add it to a fork right now; I'll take a look if I get time, and in the meantime there's an idea at least.

Hopefully this post will be helpful to someone who is suddenly blindsided by this issue like I was this morning! No idea how I've never come across this problem in the last 2 years.

vishnu-dev commented 4 years ago

Thank you for taking time for writing the answer @sapphous . The whole reason that I chose adding a new library i.e. angular2-notification over Angular Material Snackbar was that it is simple to use and call. If it is going to cause so much of an issues for just visibility then I have no reason to use it. So, I think the library should natively support this.

JanvanCasteren commented 4 years ago

a simpler solution is to not only add the element in your apps root template, but also in de template of the popup dialog. Problem solved.

fahadkhan1229 commented 4 years ago

@JanvanCasteren Not getting your point. please elaborate it

JanvanCasteren commented 4 years ago

I have <simple-notifications [options]="notificationOptions"> included in my appComponents html.

Like @deepender87 states, when using a popup dialog, the notification popups appear behind the dialog.

My solution was to simple add a second simple-notifications element inside the dialogs content section.

In my case (I use primeng dialogs):

<p-dialog  ....>
   <!-- all html between <p-dialog  ....> and </p-dialog> will be shown as dialog content -->
   <div>this is dialog content</div>
  <simple-notifications [options]="notificationOptions"></simple-notifications><!-- this notification will show render above the dialog -->
</p-dialog>
ahmed-hamdy90 commented 3 years ago

At First: I tried use solution [which suggested by @flauc -> Here ] for change z-index style, It works with me, I must override z-index of modal background overlay with values less than notification layout plus use ViewEncapsulation.None under Component like this:

Style file:

ngb-modal-backdrop.modal-backdrop {
  z-index: 9000 !important;
}

.my-modal {
  z-index: 9100 !important;
}

div.simple-notification-wrapper {
    z-index: 9999 !important;
}

Component class:

@Component({
  selector: 'app-my-modal',
  templateUrl: './my-modal.component.html',
  styleUrls: ['./my-modal.component.css'],
  encapsulation: ViewEncapsulation.None
})
export class MyModalComponent implements OnInit {}

But This solution may be bug in case there two pop-up modal into same page (one which override it's z-index and another with default Bootstrap Modal style), Scenario for Bug: when open First The override Modal style then Open The modal with default Style Will display Background overlay above model view as we use ViewEncapsulation.None into Component class.

Then: I tried use another solution [which suggested by @JanvanCasteren -> Here ] of put <simple-notification> tag with-in Modal view without any style override, it work with me Even this solution was settings duplicate <simple-notification> tag as the main one setting under app.Component class's view.(There no duplicate notifications will display)

Finally: I hope this issue will be solved using Library's Options without need to try any workaround before 2021

okocsis90 commented 3 years ago

@JanvanCasteren you saved me a few hours :) So simple