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

Error: [$compile:ctreq] Controller 'ngSwitch', required by directive 'ngSwitchWhen', can't be found! #3661

Closed
pheuter opened this issue Aug 19, 2013 · 32 comments

Comments

@pheuter
Copy link

pheuter commented Aug 19, 2013

Tried upgrading angular from 1.1.5 to 1.2.0rc1. Now, I'm getting the following error:

Error: [$compile:ctreq] Controller 'ngSwitch', required by directive 'ngSwitchWhen', can't be found!

It seems weird to me because ngSwitch is a core directive. Anyone else seeing this?

Looks like Angular has some docs on this error, but this particular directive is not a custom one that I implemented.

@Burgov
Copy link

Burgov commented Aug 19, 2013

can you show us some HTML?

@pheuter
Copy link
Author

pheuter commented Aug 19, 2013

It's a pretty large app, and the console error stack trace does not point to any local files. Have no idea what chunk of code to isolate.

@brianpetro
Copy link

Double check that all of your 'ng-switch-when' directives are wrapped in an 'ng-switch' directive.

@dg192
Copy link

dg192 commented Sep 4, 2013

I'm seeing this same error after upgrading from 1.0.7 to 1.2.0rc1. Here's my directive and markup...

Directive that inherits from the parent scope

myModule.directive('lastcontact', function() {
    return {
        restrict : 'E',
        scope : true,
        replace : true,
        templateUrl : '/views/lastcontact.html',
        link : function(scope, element, attrs) {
            console.log(element);
            $(element).find('span').on('click', function() {
                console.log('change date');
            });
        }
    };
});

Template file lastcontact.html

<div ng-switch on="project.lastContact">
    <span ng-switch-when="">
        <i class="icon icon-edit"></i>
        <span>Not contacted.</span>
    </span>
    <span ng-switch-default class="lastContact">
        <i class="icon icon-edit"></i>
        <span>Last Contact: {{project.lastContact}}</span>
    </span>
</div>

@johnsto
Copy link

johnsto commented Sep 6, 2013

I'm encountering the same issue, using code that works perfectly on 1.1.5.

It looks to be something to do with the ordering of directive controller instantiation. By popping breakpoints in I've determined that on 1.1.5, the child directive's controller is initialised before getControllers. On 1.2.0rc2 however, getControllers is being called before directive controllers have a chance to instantiate themselves, therefore failing with the missing controller error.

@sdornan
Copy link
Contributor

sdornan commented Sep 8, 2013

I'm also having this issue. In my case, with the rating directive in angular-bootstrap using a custom template.

I made a plunker to demonstrate the issue:
http://plnkr.co/edit/u1l6h0nZkCtngZttipjx

@sdornan
Copy link
Contributor

sdornan commented Sep 8, 2013

Turns out this issue goes away when using an inline template, so it appears to be related to #3792.

@scottybollinger
Copy link

Does anyone have a fix for this? Using 1.2.0rc3 and I get the same error with a similar chunk of code that dg192 posted.

@dg192
Copy link

dg192 commented Nov 1, 2013

It's been a while, but if I remember right, I had to remove to the 'replace' : true option to get it to work. My current code is working and that option is the only difference. I'm using 1.2.0rc2.

@scottybollinger
Copy link

Thanks for the response. I didn’t have replace: ‘true’ but I was able to work around it using a bunch of no-show’s. Hopefully the AngularJS team can help with a workaround in the future

@scottybollinger
Copy link

*ng-show's. Autocorrect FTW

@markschaake
Copy link

I'm experiencing the same problem in 1.2.0 (official release). The only workaround that works for me is to specify the template inline. Mucking with the "replace" attribute has no affect.

@avijassra
Copy link

same issue .... template too big to be inline .... :(

@michael-wirth
Copy link

same issue with 1.2.4
ngSwitch doesn't work inside a template. It doesn't matter if its inline or loaded by templateUrl, nor does the 'replace' attribute have any effect on this

@caitp
Copy link
Contributor

caitp commented Dec 11, 2013

@t4gedieb is this not working correctly in 1.2.4? I can't seem to reproduce the issue (or maybe it's not clear what is broken)

Maybe instead something more like this (which is also working?) I don't understand the issue :(

@jordymeow
Copy link

Same here, ng-switch in a template is not working on Angular 1.2.4.

@caitp
Copy link
Contributor

caitp commented Dec 12, 2013

Please provide a demonstration of it not working, as far as I can tell it is working fine

@michael-wirth
Copy link

I found out that MY problem only occurs if I use "ng-switch-when" and "ng-switch-default" on elements.

I did put together a little example: http://jsfiddle.net/t4gedieb/yYR3y/

Template with - fails

<ng-switch on="option">
  <td ng-switch-when="1">NG-SWITCH-WHEN-1</td>
  <td ng-switch-when="2">NG-SWITCH-WHEN-2</td>
  <td ng-switch-default>NG-SWITCH-DEFAULT</td>
</ng-switch>

Template with
- works

<ng-switch on="option">
  <div ng-switch-when="1">NG-SWITCH-WHEN-1</div>
  <div ng-switch-when="2">NG-SWITCH-WHEN-2</div>
  <div ng-switch-default>NG-SWITCH-DEFAULT</div>
</ng-switch>

@caitp
Copy link
Contributor

caitp commented Dec 12, 2013

There is a problem compiling table content nodes right now... I have a patch for this, but as usual it's not certain it will be merged. similar problems exist for other content types like SVG content. #5235

edit hmm, I guess this doesn't work for templateUrl, only templates so far! I guess I have some work to do today.


http://plnkr.co/edit/lElPZH9qlOemGE8vpteH?p=preview there, fixed that... using that PR you can probably get this working, although that example isn't quite what you were doing. Pretty close though.

http://plnkr.co/edit/9rg68DVp0w5kfc727mCj?p=preview this is probably closer to what you're doing

@EvgenyGusev
Copy link

+1

@farolfo
Copy link

farolfo commented Feb 21, 2014

+1 here, is there any update here?

I'm having the same issue with the td.

@caitp
Copy link
Contributor

caitp commented Feb 21, 2014

@farolfo: http://plnkr.co/edit/h1DhBBTr7Xq94HMiopfn?p=preview.

Table content is now supported in replace templates. HOWEVER, you can't really put <ng-switch> elements into a table by themselves, so you need to be a bit clever. There isn't really anything we can do about this, as this is the fault of the HTML parser in the browser. But, if you want to, you can do something like the example I provided above. (Note that that would have worked even prior to 1.2.13)

@farolfo
Copy link

farolfo commented Feb 21, 2014

Thanks a lot @caitp !

BTW I've just found this using ng-show inside of a table, do you know if this is a known issue ? Or may be I'm missing something .
http://jsfiddle.net/HB7LU/2323/

@caitp
Copy link
Contributor

caitp commented Feb 21, 2014

@farolfo: http://dev.w3.org/html5/markup/tr.html#tr-content-model --- the <div> element is not allowed to be a child of a <tr> element. This is the HTML parser in the browser, not Angular, and we have no way to work around this.

@caitp
Copy link
Contributor

caitp commented Feb 21, 2014

Anyways, I think we should close this issue, as the only remaining complaints seem to be issues with the browser's HTML parser. I'm not able to reproduce any of the reported async vs sync directive issues on 1.2.13. So I think we're done here, yay.

@caitp caitp closed this as completed Feb 21, 2014
@farolfo
Copy link

farolfo commented Feb 21, 2014

Didn't knew that ! Thanks !!

@mindjuice
Copy link

I ran into the same error with a different root cause when using Angular with gulp-minify-html. It turns out that, by default, gulp-minify-html removes empty attributes from the HTML. This is obviously deadly for Angular apps.

It also manifested with ng-include not working and some custom attributes not working that were all fine before I switched from mimosa to gulp for my build system.

To fix it, I changed my gulp rule to pass {empty:true} in the options to minifyHTML(), which means "do not strip empty attributes". My new gulp task looks like this:

var minifyHTML = require('gulp-minify-html');

gulp.task('htmlmin', function() {
   var htmlSrc = './app/index.html',
   htmlDst = './public/';
   var opts = {empty: true};

   gulp.src(htmlSrc)
      .pipe(changed(htmlDst))
      .pipe(minifyHTML(opts))
      .pipe(gulp.dest(htmlDst));
});

See docs here for more information on other optimization flags: https://www.npmjs.org/package/gulp-minify-html

I spent far too long tracking this down, so hopefully this helps someone else in the future.

@caitp
Copy link
Contributor

caitp commented Sep 17, 2014

Thanks for the tip, users of code obfuscators will appreciate it

@mindjuice
Copy link

Hi Caitlin, regarding your previous (deleted?) comment about minifying HTML being a silly form of obfuscation, the reason I minify HTML is not obfuscation, it is to reduce download size.

Imagine how much less Internet traffic there would be if all websites minified their HTML!

In my case it was a 20% savings in file size for my one index.html file (a SPA), and that was a pretty simple file without many comments or much indentation. Other files can have significantly larger savings.

@caitp
Copy link
Contributor

caitp commented Sep 18, 2014

I know why you're doing it, but the thing is, gzip/deflate can do the hard work without requiring obfuscation, and the difference is pretty much negligible, especially when there is a lot of repeated content like CSS classes or attributes or element names.

The comment was a joke, however the fact is, the end result of minfication is obfuscation, and there are ways of shrinking download size significantly which don't require this.

@mindjuice
Copy link

Sure, gzip is great, but minification + gzip is significantly better than gzip alone. One example: http://stackoverflow.com/questions/807119/gzip-versus-minify

Also, IMO, the mild obfuscation that takes place isn't a negative thing as you seem to imply. I doubt anyone wants to look at my site's HTML, but if they do they can either use Chrome developer tools to see it (Inspect Element) or use View Source and run it through a beautifier with a simple copy/paste in about 5 seconds (e.g., http://jsbeautifier.org/).

To me, with a tool like gulp-minify-html, the process is automatic and is a net positive. I see no reason to not use it (once past the silly default of removing empty attributes).

YMMV

Anyway, this is going off topic now. :-)

@jharaphula
Copy link

Its wise to use Switch Case in place of if then else if you have more the 5 to 6 Conditions. Nice to read this article. Well described about in-build Switch directives. To make your learning easier here I am sharing one more link http://jharaphula.com/how-to-use-switch-case-in-angularjs. These are the pure examples.

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