Reputation: 3390
I have simple HTML form named myForm
. One of the form fields has ng-if="true"
on it.
console.log(myForm)
shows that the form is an array containing 5 items.
console.log(myForm.length)
returns the number 4.
Please see the example http://plnkr.co/edit/MHi6FpEs9l0wbC96Cx6b?p=preview
Upvotes: 1
Views: 724
Reputation: 8978
This hung me up recently as well, and after looking into it a little I believe the issue is that ng-if sets a $watch in its link function, so even though your directive's link function may execute after ng-if, the $watch
won't be triggered until the next $digest
(or later in the same one? Not entirely sure).
So both directives are compiled, then linked, and finally $watch
is triggered and the ng-if DOM element is inserted.
If you wrap your code in a $timeout
it will reflect the proper value, as the $digest
will have completed:
http://plnkr.co/edit/T8dXfRhsgFWGg0I232Vo?p=preview
The reason that the console shows the length of the form as 4 is because when your directive link function runs, ng-if has been compiled which removes your input from the DOM and replaces it with a comment that looks like <!-- ngIf: true -->
, but the $watch
declared in the ng-if link function has not run yet.
ng-if is waiting on the $watch
to then add a clone of your input back to the DOM if the $watch
expression is truthy, but since it hasn't run at the time of your link function and a comment is not a valid form input, the form length is 4.
Order of events if I understand it correctly:
Form.length returns 4 despite there still being 5 elements because as per the spec, form.length returns the length of the elements array, which includes button, fieldset, input, keygen, object, output, select, and textarea but not div :)
The reason console.log shows a length of 4, but 5 valid inputs is because you are passing in a reference to the form element. At least in Chrome, an instant snapshot of the object passed in to console.log is displayed in italics, but when you click to expand the object in the console the current object that is referenced is shown, which is why the form is shown to have 5 valid inputs. Unfortunately the snapshot in italics is condensed, so you can't see from the console.log that the form only has 4 inputs.
If you clone the input at the time of the console.log you can see that it actually doesn't have the 5th input.
var myFormClone = myForm.cloneNode(true);
console.log(myForm) //has 5 inputs by the time you see it
console.log(myFormClone) //has 4 inputs
Relevant chromium issue: https://code.google.com/p/chromium/issues/detail?id=50316
Upvotes: 3