CraigR8806 CraigR8806 - 9 days ago 7
AngularJS Question

Modal inside of scrollable pane generated by directive being partially hidden in IE11

Before I begin, I am completely aware that internet explorer is the kid in the corner eating paste when it comes to web browsers. However, bootstrap's modals seem to work fine in ie everywhere else throughout my webapp.

A little backstory... I am creating a medium to large webapp with Angular 1.5.5 and Bootstrap 3.x and it needs to be supported in both IE and FF (great fun huh? no really, it is a constant struggle)...

One of the components of my app is a scrollable div inside of a panel-body that has an ngRepeat that generates custom directives from an array of objects. Each of these directives gets different data to display, one of which is an array of items that it "contains".

On each of these directives is a remove button that allows the user to remove selected items from the directive and a delete button that allows the user to fully delete the directive and all item associations with that directive. To apply this functionality, I am trying to use a modal for confirmation of deletion and removal. The modal that appears upon removal is to show the items that are to be removed as well, so I need to be able to supply both the array of items that need to removed and the directive "name"(i.e. id).

The problem that exists (and only in IE) is that because the directives are within a scrollable div, the modal that is generated by the directive is also considered to be within the scrollable div and the portion of the modal (the header and part of the body) that lie outside of the scrollable div, are cut off. This only happens in IE and like I stated earlier, there are plenty of other modals throughout the project that work with IE, just none that reside within a scrollable div.

Solutions that I have toyed with in my mind are as follows.


  • Use angular-ui-bootstrap: the project takes some time to load as it is already because it is so massive and I would like to try to avoid adding another heavy piece to it

  • Have the modals declared outside of the directive: Now this is an interesting idea, however, the problem with this is that directive A would need to call a method that was provided to it from the parent controller through and attribute to open the modal. Then the parent controller would need to wait until the user clicks the OK button on the modal and then it would need to return the results to the directive, but at this point



A:the parent controller would have no knowledge of which directive made the call to open the modal (I could set a var in the parent stating which directive made the call but...)

B: even if the parent controller knew which directive made the call, it would still need to invoke a function that lives within the directive that made the call and due to the nature of scope in angular, the parent controller has no knowledge of the functions that live inside a child directive.

I know this was a bit long winded and probably really boring to read, but I wasn't sure of any other way to condense it and still get my point across.

Answer

I fixed this issue by placing the Modal outside of the directives. The directives now call a method belonging to the parent controller letting the parent controller know that it needs to display the modal and sending it the data to display within it as well as a function reference to call upon promise return. I then create a promise that is resolved upon user input within the modal. If the promise returns in a positive fashion, the parent controller generates another promise by making an http call to the server and that promise is returned to the original directive that made the call.

This was all made possible because of promises. Had I not used promises, the parent controller would not have knowledge of which directive made the call at the time of user input from the modal.

function openModal(modalRequestData){
    var promise = generateModalPromise(modalRequestData);
    promise.then(function(response){
        //do some stuff
        if(response){
            var httpPromise = //make http call
            httpPromise.then(function(out){
                //do some stuff regarding result of http call 
            }
            modalRequestData.functionToCall(httpPromise);
        }
    }
}