Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Combination of transclude, templateUrl, require produces "Error: [$compile:ctreq] Controller 'foo', required by directive 'blubb', can't be found!" #14768

Closed
wimute opened this issue Jun 14, 2016 · 2 comments

Comments

@wimute
Copy link

wimute commented Jun 14, 2016

Dear angular guys,
we encountered following unexpected error message while using a combination of transclude with fallback content, templateUrl, and require:

angular.js:13642 Error: [$compile:ctreq] Controller 'foo', required by directive 'blubb', can't be     found!
http://errors.angularjs.org/1.5.6/$compile/ctreq?p0=foo&p1=blubb
    at angular.js:68
    at getControllers (angular.js:9237)
    at getControllers (angular.js:9244)
    at nodeLinkFn (angular.js:9160)
    at compositeLinkFn (angular.js:8459)
    at nodeLinkFn (angular.js:9151)
    at angular.js:9496
    at processQueue (angular.js:16104)
    at angular.js:16120
    at Scope.$eval (angular.js:17378)

The error occurs in following situations:

  • A directive "bar" is defined with transclusion and an embedded fallback content
  • The embedded fallback-content contains a directive "barr" which template is loaded via templateUrl
  • The template of "barr" contains a directive "blubb" which requires a top controller "foo"
  • Directive "bar" is used and own content is provided so the transclusion fallback content should be discarded.

The error does not show up, if no content on "bar" is provided and fallback content is used. Either it does not show up if template is provided via "template"-property and not "templateUrl"-property.

It looks like the error has no functional impact and just produces noise in the javascript console.

Reproducable: always
Browsers: Chromium 50, Firefox 46
Operating system: Linux
AngularJs: 1.5.6, 1.4.0, 1.3.0

Steps to reproduce:

You can run this: https://plnkr.co/edit/0r3IFyL8og0Wo4sGIPBW

Or use following code:

<!DOCTYPE html>

<html>

<head>
  <script data-require="[email protected]" data-semver="1.5.6" src="https://code.angularjs.org/1.5.6/angular.js"></script>
  <link rel="stylesheet" href="style.css" />
</head>

<body ng-app="myApp">
  <div foo>
    <!-- Produces error in console -->
    <bar>Hi there!</bar>
    <!-- Works fine -->
    <bar></bar>
  </div>

  <script>
    angular.module('myApp', [])
      .directive('foo', function() {
        return {
          restrict: 'A',
          controller: function(){}
        };
      })
      .directive('bar', function($templateCache) {
            return {
              transclude: true,
              template: '<ng-transclude><barr></barr></ng-transclude>'
            };
      })
      .directive('barr', function($templateCache) {
        $templateCache.put("tmpl/barr.html", '<div blubb>Hello World!</div>');
        return {
          templateUrl: 'tmpl/barr.html'
        };
      })
      .directive('blubb', function() {
        return {
          restrict: 'A',
          require: ['^foo'],
          link: function() {}
        };
      })
  </script>
</body>

</html>

update 1:
Our expected behaviour is that if the "fallback content" from a transclude is not used there should be no lookup of required controllers from any directives from inside this discarded "fallback content".

@gkalpak
Copy link
Member

gkalpak commented Jun 14, 2016

Seems similar to #14765 (but I'm not sure).

@dcherman
Copy link
Contributor

@gkalpak Was going to tinker with this later since I've had to work around this in my own code. The gist of the problem is that the "fallback" content isn't handled correctly.

ngTransclude needs to be terminal or something such that if $transclude returns content, then the fallback child content isn't compiled and linked. There's also technically an unreported memory leak that I noticed here that's very related; if there was fallback content that created scopes and stuff, those scopes aren't cleaned up when the transclusion occurs, so it's wasted memory/watchers/etc.

That all goes away if it's made terminal and manually calls $compile on the contents only if necessary.

dcherman added a commit to dcherman/angular.js that referenced this issue Jun 14, 2016
If the transclude function did not return content, then the transcluded
scope that was created needs to be cleaned up in order to avoid a slight
amount of unnecessary overhead since the additional scope is no longer
needed.

If the transcluded content did return content, the the fallback content
should never have been linked in the first place as it was intended to be
immediately removed.

Fixes angular#14768
Fixes $14765
dcherman added a commit to dcherman/angular.js that referenced this issue Jun 14, 2016
If the transclude function did not return content, then the transcluded
scope that was created needs to be cleaned up in order to avoid a slight
amount of unnecessary overhead since the additional scope is no longer
needed.

If the transcluded content did return content, the the fallback content
should never have been linked in the first place as it was intended to be
immediately removed.

Fixes angular#14768
Fixes angular#14765
dcherman added a commit to dcherman/angular.js that referenced this issue Jun 14, 2016
If the transclude function did not return content, then the transcluded
scope that was created needs to be cleaned up in order to avoid a slight
amount of unnecessary overhead since the additional scope is no longer
needed.

If the transcluded content did return content, the the fallback content
should never have been linked in the first place as it was intended to be
immediately removed.

Fixes angular#14768
Fixes angular#14765
@Narretz Narretz added this to the 1.5.x milestone Jun 15, 2016
petebacondarwin pushed a commit that referenced this issue Jun 17, 2016
If the instance of the directive does provide transcluded content, then the fallback
content should not be compiled and linked as it will never be used.

If the instance of the directive does not provide transcluded content, then the
transcluded scope that was created for this non-existent content is never used,
so it should be destroy in order to clean up unwanted memory use and digests.

Fixes #14768
Fixes #14765
Closes #14775
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants