0

I'm using an ad-hoc ngIf directive for Angular 1.0.3 acquired from this SO answer.

// effectively
app.directive("ngIf", function () {                                             
    return function(scope, element, attrs) {                                 
            if (scope.$eval(attrs.ngIf)) {                                      
            } else {                                                            
                element.replaceWith(' ');                                       
            }                                                                   
        }                                                                       
    }                                                                           
});

The element actually gets removed. If the element has ng-model (and possibly other directives) Angular will complain.

<input ng-if="msg == 'foo'" ng-model=msg>

If msg is not foo, we get

Error: No controller: ngModel

This most likely has to do with the element being removed when ngModel is evaluated.

Is there any way to rewrite the ngIf directive so that the error does not occur?

JSFiddle example

Community
  • 1
  • 1
Explosion Pills
  • 188,624
  • 52
  • 326
  • 405

1 Answers1

0

Rather than

element.replaceWith(' '); 

use

element.html('');

And it works fine. Here's a demo: http://jsfiddle.net/sd3px/

This way you're not removing the Angular attributes that were established at compile time.

Angular gets rather sad when an element is established at compile time and then is gone at link.

You can see how Angular "recreates elements using their compiled state" in it's own version of ngif (new as of 1.1.5): https://github.com/angular/angular.js/blob/4612705ec297bc6ba714cb7a98f1be6aff77c4b8/src/ng/directive/ngIf.js

Update with 1.2 test:

I was curious to see how this works with 1.2.0. Admittedly you'd probably just use Angular's ngif with 1.2. None the less your code does work in 1.2 with one minor change of using element.html(''); instead of replaceWith.

Here's a plunker showing that in action: http://plnkr.co/edit/5jUzTH43OF2PqzMEbSz4?p=preview

KayakDave
  • 24,636
  • 3
  • 65
  • 68
  • Unfortunately the `.html` solution does not remove the element itself (which is part of the problem, I'm sure) – Explosion Pills Nov 13 '13 at 18:36
  • Right- angular bound to the ng-model you created during the compile step. Obliterating it during link causes the problem you're seeing. Is it critical the surrounding element be gone? If so do you always know the name of the ng-model you'll have? We have to keep compile and link phases in sync one way or another. – KayakDave Nov 13 '13 at 19:07
  • Well the element with `ngIf` on it is an `` so it's not actually surrounding anything per se – Explosion Pills Nov 13 '13 at 19:20
  • I see what you're saying - I was thinking of my example. Would it be reasonable to use a surrounding div that has the `ng-if` on it, like this: http://jsfiddle.net/sd3px/1/ ? – KayakDave Nov 13 '13 at 19:23
  • Well that is the solution I'd come up with, but I was wondering if there was a way to have the directives work properly together in this way. – Explosion Pills Nov 13 '13 at 19:25
  • I'm assuming you're pre 1.1.5, otherwise you could use the Angular ngif. http://docs.angularjs.org/api/ng.directive:ngIf – KayakDave Nov 13 '13 at 19:28
  • Interesting to read the Angular version of ngif. Note the comments about how they recreate the compiled state elements. You could reproduce that- if you really want to.... (since I think that's exactly the issue you're running into): https://github.com/angular/angular.js/blob/4612705ec297bc6ba714cb7a98f1be6aff77c4b8/src/ng/directive/ngIf.js – KayakDave Nov 13 '13 at 19:31