とんちむ日記

RubyとJavaScriptと猫が好きです

Angularで起こった怪奇!?

ありのまま、今日起こった事を話すぜ・・・

 

input numberに999999999999999934464以上の数値を入力すると /^[0-9]*$/(0以上の数字ならOK)のパターンにマッチせずにエラーメッセージが表示されたんだ。

 

な・・・何を言ってるかわからねーと思うがおれも何をされたのか分からなかった・・・

 

 

という恐ろしい現象!?真夏の怪奇を味わいました。まぁこれなんとか原因突き止めたんですが。

 

まず999999999999999934464という数字をググってみると何やら英語のサイトを発見・・・するとどうやら999999999999999934464以上の数値は見た目にはわからないが指数表記になっている模様。

 

指数表記ってのは電卓とかでも大きな数になると1e+1とか出ますよね、あれのことです。

 

Angularのng-patternを使っていた時に発生したんですが、ほかの環境では再現されずAngularのバージョンか、またはコントローラーとかの他の部分が悪さしてるのかもしれません。(だからこの記事が役に立つことはあまりないような気がする・・・)

Angularのバージョンの問題でした。最新バージョンでは解決しているようです。

 

 

そもそもなんで$error.numberを使わないの?と思われそうですが、使ってるんですよねすでに、それだけだと小数に対応できないんですよ。

 

指数表記を数字に直してくれるような機能ないかなーと思っていたらJavaScriptのNumber.prottype.toFixed()というメソッドを発見!

 

これで直ると思いきや・・・「number が 1e+21 【訳注: e+21 は 10 の21乗】 より大きい場合、このメソッドは単純に Number.toString() を呼び出し、指数表記での文字列を返します。(MDNより引用)」

 

つ、使えねぇ・・・なぜって999999999999999934464は1e+21だからです。

 

仕方なく指数表記も加えたパターンを作りましたとさ・・・。

 

それがこちら

/^\d*((\.\d+)e\+\d+)$/

 

通常の数字でも、指数表記でも対応できます!マイナスなどにはちょっと手を加えてくださいね。

 

普通に文字として指数表記入力したらマッチしそうですがその場合は$error.numberが最初に弾いてくれるので問題ないですw

 

--追記--

よくよく考えたら$error.numberがほとんど弾いてくれるので小数点だけを省けばいい話でした・・・。

なので  /^[^\.]*$/  これでOKです。