The problem is that Angular initially replaces ngIf
with a comment that it uses to track where to place the conditional code. It's easiest to see with an example.
Your HTML:
<div control-group>
<label>Test</label>
<input type="text" ng-model="editing.name" />
<span class="text-error" ng-if="editing.name.length != 3"> Name must be 3 characters </span>
</div>
Looks like this inside your transclude function's cloned
variable (transclude(function (cloned) {
):
<div control-group>
<label>Test</label>
<input type="text" ng-model="editing.name" class="ng-valid ng-dirty">
<!-- ngIf: editing.name.length != 3 -->
</div>
So, the element with class text-error
that you're filtering on (below) isn't in cloned
. Just the comment is there.
var inputsAndMessages = cloned.filter('input, button, select, .text-error');
Since you're only transcluding elements that match the above filter the ngIf
comment is lost.
The solution is to filter for comments as well and add them in your append (so Angular maintains it's reference point to the ngIf
). One way to do that is to replace the above with this (using the fact that an html comment is node type 8)
var messages = cloned.filter(function(){ return this.nodeType == 8; }); //comments
var inputs = cloned.filter('input, button, select')
var inputsAndMessages = inputs.add(messages);