18

I am trying to call modal dialog from an angular controller. The example is pretty simple and not far from very trivial. I have code such as

$modal.open({
        template: '<div class="modal-body">Choose current project<button class="btn btn-primary" ng-click="ok()">OK</button> <button class="btn btn-warning" ng-click="cancel()">Cancel</button></div>',
        controller: ModalChooseProjectCtrl
    });

Controlling function is declared as

var ModalChooseProjectCtrl = function($scope, $modalInstance) { 
         $scope.ok = function() {
        $modalInstance.close($scope.chosenProject);
    };

    $scope.cancel = function() {
        $modalInstance.dismiss('cancel');
    };
};

and it is called from withing a controller's function that belongs to div, which contains bootstrap's navbar.

Problem: when I invoke function that has that $modal.open call, errors are shown

  Error: [$compile:tplrt] Template for directive 'modalBackdrop' must have exactly one root element. template/modal/backdrop.html 
  http://errors.angularjs.org/1.2.15-build.2378+sha.9335378/$compile/tplrt?p0=modalBackdrop&p1=template%2Fmodal%2Fbackdrop.html


  Error: [$compile:tplrt] Template for directive 'modalWindow' must have exactly one root element. template/modal/window.html
  http://errors.angularjs.org/1.2.15-build.2378+sha.9335378/$compile/tplrt?p0=modalWindow&p1=template%2Fmodal%2Fwindow.html

These errors say that template, so to speak, mut be wrapped in one html root element, which is obviosuly so from template. Additionally, after call I see that following elements appear in the code

 <div modal-backdrop="" class="ng-scope"></div>
 <div modal-window="" index="0" animate="animate" class="ng-scope"></div>

and if I click further, more modal-window appear in code. But screen just jumps and nothing happens and I do not get my modal dialog. While in Plunker the calling code for dialog shows it just fine (http://plnkr.co/edit/VJ1Kick7QWE3X0bL6gtw , but it is just basic calling routine.)

onkami
  • 8,791
  • 17
  • 90
  • 176

6 Answers6

53

This is a common issue, when you have no angular-ui templates provided.

Latest versions of angular-ui comes in two variants: ui-bootstrap.js and ui-bootstrap-tpls.js. You need to use just last one.

Provided error is not about template of your directive, but about templates of modalBackdrop and modalWindow directives that are a part of angular-ui itself. Usually, Angular cannot find templates and make a HTTP GET request getting some HTML code, like 404 error. And there are many root elements. So thats the reason why you are getting such error. Check HTTP requests on page load for.

Maxim Demkin
  • 1,215
  • 11
  • 13
  • 5
    My problem ended up being that I was only including `ui.bootstrap.modal`. This didn't load the templates. Changing it to `ui.bootstrap` solved it. – connorbode Jun 04 '14 at 22:27
  • This was exactly my problem. I was loading tpls and non tpls. So the directives were there and executing, but nothing inside. Hours of wasted work for this idiocy I did hah! At least everything will work now :) – geilt Jul 10 '14 at 00:03
3

I have resolved it by including $templateCache as controller dependency (the one that posess function that calls open). I have no idea, however, why $modal can not catch up that dependency itself.

onkami
  • 8,791
  • 17
  • 90
  • 176
  • I'd been trying to figure out why my templates were erroring out. Finally got it solved. – joncarl Jul 18 '14 at 11:19
  • @redress you simply put $templateCache into injections. This is basic angular syntax - explaining that in more detail would be strange, as it is obvuious to any angular programmer. – onkami Jan 18 '16 at 09:56
2

You can get these errors if you have called $templateCache.removeAll(). I suspect the templates the ui.bootstrap module requires are stored in the template cache so clearing the cache makes them unfindable.

nmgeek
  • 2,127
  • 1
  • 23
  • 31
0

In my case these errors were caused by bug in custom http interceptor that handle response data.

beholderrk
  • 730
  • 8
  • 17
  • Your $http.success callback was the cause ? Can you tell me more please ? – Hornth May 28 '15 at 16:01
  • I can't speak for the OP. But I have a similar issue with ui.bootstrap typeahead directive. I am using it on an index app, no routing and very simple. If my config function is empty typeahead works fine. if I conjure a custom interceptor on the $httpProvider in config phase I get: Template for directive 'typeaheadPopup' must have exactly one root element. – hippeelee Jun 26 '15 at 20:12
0

I'm using bower for my front-end depency.

As recommanded in the angular-bootstrap FAQ,

I changed my depenncy injection from 'ui.bootstrap.modal' to 'ui.bootstrap'

something like that :

angular.module('myApp', ['ui.bootstrap']).run(...
Tony
  • 11
  • 1
  • 3
-1

adding ui-bootstrap-tpls-[version].min.js file should resolve the issue.