1

I am writing a directive to cooperate with ngModel. As shown in the example, I set the $render function on the controller to my function.

When the code initializes, it is invoked twice, the first time with $modelValue and $viewValue set to NaN, and then a second time with the actual value of the model.

The problem is, NaN is a bear to test for. The function isNaN() is worthless, so far as I can see (it returns false for [""] but true for ["."]) and Number.isNaN() is not widely supported.

Any suggestions?

Michael Lorton
  • 43,060
  • 26
  • 103
  • 144
  • So, is the question really how to determine that `NaN` is `NaN`? – New Dev May 18 '15 at 22:47
  • Hmm, should be undefined for the first call. – Riad Baghbanli May 18 '15 at 22:59
  • you didn't list the example you mention, but what is the directive doing that it needs to be in the middle of the `$render` cycle in the first place? – Claies May 18 '15 at 23:04
  • @NewDev -- "How to determine that `NaN` is `NaN`?" is the $64,000 question but the answer seems to be, you don't. If something passes `angular.isNumber()` but not `isFinite()` then it is definitely NaN. Or one of the infinities... – Michael Lorton May 18 '15 at 23:12
  • @rbaghbanli -- no, it's undefined in the second call if the model is undefined. – Michael Lorton May 18 '15 at 23:14
  • @Claies -- I am trying to provide a default value if the model value is set, but invalid. – Michael Lorton May 18 '15 at 23:15
  • @Malvolio, I'm not sure how you are getting `NaN` - in a trivial case ([plunker](http://plnkr.co/edit/TKD8wpAbsxY2SKhqk85h?p=preview)) if model is not set, it is `undefined`. Off-topic, but setting a default value doesn't seem to me like the right thing to do. A model is what drives the View - not the other way around. Take ` – New Dev May 18 '15 at 23:36
  • @NewDev -- your example proves that *in some cases*, the modelView is `undefined`, not in every case. [This answer](http://stackoverflow.com/a/16384177/238884) shows how `NaN` is also a possibility. Your example makes the situation worse, because I cannot rely on the first call being "bad". – Michael Lorton May 18 '15 at 23:42
  • @Malvolio, ok, yes, `$modelValue` and `$viewValue` are `NaN` in the *very beginning* (during link-time), before `$formatters` run and before `$render` (which is why the example you provided has `NaN`). This example will help to illustrate: http://plnkr.co/edit/WPR9oYTZ5IKWOLRUsSiw?p=preview – New Dev May 19 '15 at 00:14

2 Answers2

0

I came up with a partial answer to my question, about how to test for NaN, but it still seems awkward to me.

Community
  • 1
  • 1
Michael Lorton
  • 43,060
  • 26
  • 103
  • 144
0

The $modelValue and $viewValue of ngModel only ever assume (unless specifically assigned) the value of NaN in the very beginning - at link-time - and before any $formatters, $render and $validators (in that order) had a chance to run.

In other words, if you were to log at various points these values, you'd get the following (assuming the ngModel variable is set to "foo"):

              link-time    $formatters     $render     $validators
              -----------------------------------------------------
$modelValue     NaN           "foo"         "foo"         "foo"
$viewValue      NaN            NaN          "foo"         "foo"

Demo

In words, unless you need to access ngModel at link-time, there is no need to guard against NaN. Moreover, there is also no double invocation - the ngModel pipe runs once per change.

Given the example you cite in comments my guess that you are seeing NaN in the $render function because you manually invoke the $render at link-time.

New Dev
  • 48,427
  • 12
  • 87
  • 129
  • ngModel is only available to me at link-time. – Michael Lorton May 19 '15 at 22:09
  • Of course it is, but `$render` doesn't need to run at link time - `ngModel` runs it when model value changes or set for the first time – New Dev May 19 '15 at 22:21
  • Dunno what to tell you. ngModel _is_ running $render at link time, with the value set to NaN. – Michael Lorton May 19 '15 at 23:17
  • @Malvolio, try to repro then. The only other thing I can think of is that another directive that also does `require: "ngModel"` initiates rendering – New Dev May 19 '15 at 23:47
  • They are input elements in a form -- doesn't Angular naturally require `ngModel` so as to keep the FormController up to date? – Michael Lorton May 20 '15 at 01:54
  • @Malvolio, yes, all input elements `require: "ngModel"`, but they also provide `$render`, so you shouldn't be re-defining it. `$render` should be defined if you are the one who implements the model-to-DOM translation. So, I'm confused about what you are trying to achieve – New Dev May 20 '15 at 02:08