æåã®éšåã§ã¯ãæ°ããããŒãžã§ã³ãžã®ç§»è¡ã®äž»ãªåé¡ããã¹ãŠæ€èšããŸããããããã§äœãããã®ãã«ã€ããŠè§ŠããŸãã

åè¿°ã®ããã«ãç§»è¡ã®äž»ãªçç±ã¯ãã¢ããªã±ãŒã·ã§ã³ã®é床ã倧å¹
ã«åäžããããšã§ãïŒJeff CrossãšBrian FordãngEuropeäŒè°ã§è¿°ã¹ãããã«ãDOMã§ã®æäœã4.3åã $digestãµã€ã¯ã«ã3.5åïŒ1.2ãšæ¯èŒïŒ ã
ãã ãããã®é床ã¯äž»ã«å
éšã®æé©åãšéæ³ã«ãããã®ã§ã¯ãªããã³ãŒããããå¹ççã«èšè¿°ã§ããããŒã«ã®æäŸã«ãããã®ã§ãã
ãããã®ããŒã«ãèŠãŠã¿ãŸãããïŒ
ãããã°æ
å ±
ã¢ã³ã®ã¥ã©ãŒããªãœãŒã¹ã®å€§éšåããã¯ã©ã¹ã®è¿œå ãªã©ã®ãããã°ã容æã«ããæ
å ±ã«è²»ãããŠããããšã¯ãã¥ãŒã¹ã§ã¯ãããŸãã
DOMèŠçŽ ïŒ ng-bindingããã³ng-isolated-scopeã¯ã©ã¹ãªã©ïŒãŸãã¯ãããã«ããŸããŸãªã¡ãœãããã¢ã¿ããããŠscopeã«ã¢ã¯ã»ã¹ãscope ïŒããšãã°.scope()ããã³.isolateScope() ïŒã
ãããã¯ãã¹ãŠãå床åšããã¿ã©ã³ãªã©ã®ããŒã«ã®äœæ¥ã«åœ¹ç«ã¡ãå¿
èŠã§ããããã®ããŒã¿ã¯çç£ã«å¿
èŠã§ããïŒ
ããŒãžã§ã³1.3以éããããã°æ
å ±ãç¡å¹ã«ã§ããŸãã
 app.config(['$compileProvider', function ($compileProvider) { $compileProvider.debugInfoEnabled(false); }]); 
ãããã補åã販売ããå¿
èŠãããããããã°ãç¡å¹ã«ãªã£ãŠããå Žåã¯ã©ãã§ããããïŒ
ããã§ã¯ã angularãªããžã§ã¯ãã®.reloadWithDebugInfo()ã¡ãœãããä¿åããã angularãªããžã§ã¯ãã¯ã°ããŒãã«ãªã®ã§ãã³ã³ãœãŒã«ãããã®ã³ãŒããç°¡åã«å®è¡ã§ããŸãã
 angular.reloadWithDebugInfo(); 
$ applyAsync
ããŒãžã§ã³1.3ã§ã¯ã $applyAsyncãµãŒãã¹ã$applyAsyncããŸãããå€ãã®ç¹ã§ããã®ã¡ã«ããºã ã¯æ¢åã®$evalAsyncãµãŒãã¹ãšäŒŒãŠããŸãã
ç°¡åã«èšãã°ãåŒããã¥ãŒã«è¿œå ããŠããåŸ
æ©ãïŒsetTimeoutïŒ...ã0ïŒãèšå®ããææ°ã®ãã©ãŠã¶ãŒã§ã¯çŽ10ããªç§ã§ãïŒãéå»ã«å¥ã®åŒããã¥ãŒã«è¿œå ãããŠããªãå Žåã¯ãéå§ããŸã
$rootScope.$digest() ã
ããã«ãããåã$ãã€ãžã§ã¹ãã«ãŒãã§å®è¡ããã$ applyãé »ç¹ã«åŒã³åºãããšãå¿é
ããã«ãDOMã«åœ±é¿ããå€ãã®åæåŒãå®è¡ã§ããŸãã
$ evalAsyncãšã®éãã¯äœã§ããïŒ
äž»ãªéãã¯ã $applyAsyncèªäœãããŒãã£ãã§ãã¯ã®åã«$digestãµã€ã¯ã«ã®éå§æã«åŒãã¥ãŒå
šäœãå®è¡ããããšã§ããããã«ããã $evalAsyncã¯ããŒãã£ãã§ãã¯äžã«å®è¡ãã $evalAsync ïŒããæ£ç¢ºã«ã¯ã ïŒããŒãã£ãã§ãã¯ãµã€ã¯ã«ã®éå§ïŒãããã³ãã¥ãŒã«è¿œå ãããåŒïŒ$ãŠã©ããã®å€éšïŒã¯ã$ãã€ãžã§ã¹ããµã€ã¯ã«ãåã³éå§ããŸããããã«ãããåã$digeståŒãç¹°ãè¿ãå®è¡ãããŸãã
[詳现]
ãã ãããã®ããŒã«ã䜿çšããããšã®æ¬åœã®å©ç¹ã¯ãè§åºŠã®å
éšãµãŒãã¹ãããšãã°$httpProviderãŸãã
$ http
$httpãµãŒãã¹ãšXHRãªã¯ãšã¹ããè¡ãä»ã®æ¹æ³ãšã®äž»ãªéãã¯ãå®äºæã«$applyåŒã³åºãããšã§ãã
åé¡ã¯å€ãã®äžŠåã¯ãšãªã§ããããããããå®äºæã«$applyãããã¬ãŒãã«ã€ãªãããŸãã
ãã®åé¡ã¯ãããŒãžã§ã³1.3ã® $applyAsyncã®å°çã«ãã解決ãããŸããã
 app.config(function ($httpProvider) { $httpProvider.useApplyAsync(true); }); 
ãã®ã³ãŒãã«ã¯ã $applyAsyncå
ã§ã®$httpProvider $applyAsync䜿çšãå«ãŸã$applyAsync ã
ããã«ãããåæèŠæ±ã®ãã¹ãŠã®çŽæãresolvedãšãã«1åã ã$ applyãå®è¡ã§ããããã©ãŒãã³ã¹ã倧å¹
ã«åäžããŸãã
äžåºŠãã€ã³ã
AngularJSã®äž»ãªããã©ãŒãã³ã¹ã®åé¡ã®1ã€ã¯ãåæ¹åã®ãã€ã³ãã£ã³ã°ããã¹ãŠã®åŒã«é©çšãããŸããããã¹ãŠã®ããŒã¿ããããå¿
èŠãšããããã§ã¯ãªããšããäºå®ã«èµ·å ãã$watchã®èšå€§ãªéã§ãã
éçããŒã¿ã®å Žåãäžæ©ãã€ã³ãããã ãã§ååã§ãããã«ã¹ã¿ã ãã£ã¬ã¯ãã£ãã«ãã£ãŠãããæ±ºå®ãããåã«ãããŒãžã§ã³1.3ã§ãã¹ãŠã倿ŽãããŸããã
ããŒãžã§ã³1.3以éãæ°ããæ§æã¯ãåŒã®å
é ã«::ã®åœ¢åŒã§äœ¿çšã§ããŸãã
::å§ãŸãåŒã¯äžæ¹åã®ãã€ã³ãã£ã³ã°ãšããŠèªèãããåŒã®ããŒã¿ãå®å®ããŠæåã®$digestãµã€ã¯ã«ãçµéãããšããã«è¿œè·¡ïŒç£èŠè§£é€ïŒãããªããªããŸãã
äŸïŒ
 {{:: foo }} <button ng-bind=":: foo"></button> <ul> <li ng-repeat=":: foo in bar"></li> </ul> <custom-directive two-way-bind-property=":: foo"><custom-directive> 
ããŒã¿ã®å®å®æ§ïŒ
ããŒã¿ã¯ã undefinedéãäžå®å®ã§ãããšèŠãªãããŸãã NaN ã false ã '' []ãŸãã¯nullãããã§ãã£ãŠããä»ã®ããŒã¿ã¯å®å®ããŠãããšèŠãªããã unwatchåŒã«ãªããŸãã
ããã¯ãæåã®$ãã€ãžã§ã¹ããµã€ã¯ã«äžã«å©çšã§ããªãéçããŒã¿ã«å¿
èŠã§ãã
ããšãã°ãããŒã¿ããµãŒããŒããéä¿¡undefinedããå Žåããªã¯ãšã¹ããåŸ
æ©ããŠããéã倿°ã®å€ãundefinedãŸãŸã«ããããšãã§ããŸãã ãã®éãã£ãšããã®åŒã®ãŠã©ããã£ãŒã¯åç¶ãã undefined以å€ã®ããŒã¿ãã€ã³ã¹ããŒã«ããåŸã«ã®ã¿ããã®çµæãè¿ããŸãã
::ãå«ãåŒã宿°ãšããŠæ±ããŸããäžåºŠèšå®ãããšã倿Žã§ããªããªããŸãã
æŽæ°äžå¯ã®æŽæ°ïŒ
100ã®ãã¡99ã®ã±ãŒã¹ã§æŽæ°ãããªãåŒããããšä»®å®ããŸãïŒã€ãŸãããªãŒããŒãŠã©ããã§ããã«é¥ãããšã¯ãããŸããã§ããïŒããå Žåã«ãã£ãŠã¯å¿
èŠã«ãªããŸãã ã«ãªãæ¹æ³ ãã€ã³ãã¯ã³ã¹åŒã匷å¶çã«æŽæ°ã§ãããã©ããçåã«æããŸããã
ããããã§ããŸãã:)ãã ããç¬èªã®å±æ§ãã£ã¬ã¯ãã£ããäœæããŠãç¹å®ã®ã€ãã³ãã«å¿ããŠãã£ã¬ã¯ãã£ãå
šäœãåã³ã³ãã€ã«ããããã«åŒ·å¶ã§ããŸãã ããã«äŸããããŸã ã
ããã©ãŒãã³ã¹ã®ãã®éšåã¯çµäºãã玠æµãªå©ç¹ã«ã€ããŠè©±ãããšãã§ããŸãã
ngModelãªãã·ã§ã³
ããŒãžã§ã³1.3ã§ã¯ã ng-modelã«å ããŠãã¢ãã«ãæŽæ°ãããã¿ã€ãã³ã°ãæ
åœng-modelè£å©ãã£ã¬ã¯ãã£ãng-model-optionså°å
¥ãããŸããã
æŽæ°æéã¯2ã€ã®èŠå ã«äŸåããŸãã
1ïŒ updateOnã¢ãã«ãæŽæ°ãããç¹å¥ãªã€ãã³ãïŒã€ãã³ãïŒãããšãã°ã blur ã clickãŸãã¯ããçš®ã®ã«ã¹ã¿ã ã€ãã³ãã§ãã ããã©ã«ãã¯åžžã«default ãã€ãŸããåã³ã³ãããŒã«ã¯ç¬èªã®ã€ãã³ãã䜿çšããŸãã {event: "default customEvent"}ã€ãã³ãã远å ããŠæšæºã€ãã³ããæ¡åŒµããdefaultã¯ããªã¹ãã«defaultã远å ããããšãå¿ããªãã§ãã ããïŒäŸïŒ {event: "default customEvent"} ã
2ïŒ debounce -æ°ããããŒã¿ãèŠè¶ããŠã¢ãã«ãæŽæ°ãããšãã®é
å»¶ïŒããã©ã«ãã¯0ãã€ãŸã峿ïŒã å
¥å{debounce: 300}ãæå®ãã300ããªç§æªæºã®ééã§3æåãå
¥åãããšãã¢ãã«ïŒããã³ããŸããŸãªã¢ãã£ãã¡ã€ã€/ããªããŒã¿ïŒãäžåºŠã ãæŽæ°ãããŸãã ããã«ã debounceãã€ãã³ããšçµã¿åãããŠãåã€ãã³ãã®é
å»¶ã瀺ãããšãã§ããŸããäŸïŒ {event: "default customEvent", debounce: {default: 0, customEvent: 400}} ã
ããã«ãããå€ãã®èªè»¢è»ããªããããšãã§ãïŒãããªãsetTimeout / clearTimeoutïŒãããã©ãŒãã³ã¹ã倧å¹
ã«åäžãïŒ $digest ã $watchersãã¹ãŠã®$watchersã®ç¡é§ãªåèµ·åã$watchers ïŒããŸãéåææ€èšŒã®èª€æ€ç¥ã®æ°ãæžããŸãïŒãã ãã $httpãã®ãµãŒãã¹ã¯ããªã¯ãšã¹ããã¹ãã ããªãããã«ååã«ã¹ããŒãã§ãããå®å®ããããŒã¿ãåŸ
ã¡ãŸãã
ããããããã«3ã€ã®äŸ¿å©ãªãªãã·ã§ã³ããããŸãã
allowInvalidãã©ã°ã䜿çšãããšãå€ãç¡å¹ãªå Žåã§ã$modelValueãèšå®ã§ããŸã ïŒããã©ã«ãã§ã¯ãå€ã¯ç¡å¹ã§ããã undefinedã¢ãã«ã«æžã蟌ãŸããŸããããã«ãããããšãã°äžéå€ãèŠã€ããããšãã§ããŸããïŒ
setterGetterãã©ã°ã䜿çšãããšãç¬èªã®é¢æ°ãngModelãšããŠèšå®ã§ããŸã ãããã¯ngModel.viewValue ngModel.modelValueãšngModel.viewValueéã®äžçš®ã§ãããã»ãã¿ãŒããã³ã²ãã¿ãŒãšããŠæ©èœããŸãã plunkerã®ã©ã€ãäŸ ã
ã¿ã€ã ãŸãŒã³ã䜿çšãããšãæéïŒ dateãŸãã¯time ïŒã«é¢é£ããã³ã³ãããŒã«ã®ã¿ã€ã ãŸãŒã³ãèšå®ã§ããŸããããšãã°ã '+0430'ã¯ã4æé30åGTMããæå³ããŸãã ããã©ã«ãã§ã¯ããã©ãŠã¶ã®ã¿ã€ã ãŸãŒã³ã䜿çšãããŸãã
updateOnãšãããŠã³ã¹ãç¡èŠãã
ã¢ãã«ãæåã§èšé²ããå Žåãã€ãã³ãã§èšå®ãããé
å»¶ãç¡èŠããŠãããã«æŽæ°ãå®è¡ããå¿
èŠãããå ŽåããããŸãã ããã«ã¯ngModelCtrl.$commitViewValue()ã¡ãœããããããŸãã
倿Žããã£ã³ã»ã«
debounceããã»ã¹äžã«ãã³ã°ããŠãããã¹ãŠã®å€æŽãå
ã«æ»ãããå Žåããã¥ãŒãã¢ãã«ã®çŸåšã®ç¶æ
ã«èª¿æŽããã¡ãœãã$rollbackViewValue() ïŒä»¥åã®$cancelUpdate() ïŒããããŸãã
ãã®æ©èœã®äœ¿çšäŸãšããŠãå
¬åŒããã¥ã¡ã³ãã«ã¯å
¥åããããESCãæŒããšå€æŽãããŒã«ããã¯ã§ããŸãã
詳现ãªããã¥ã¡ã³ã
æ€èšŒ
ãŠãŒã¶ããªãã£ã®é¢ã§ã®äž»èŠãªæ¹åç¹ã®1ã€ã¯ããã©ãŒã ã®æ€èšŒã§ãã
以åã¯ã ndModel.$formattersããã³ndModel.$parsersãä»ããŠæ€èšŒã¡ã«ããºã ãå®è£
ããå¿
èŠãããã ndModel.$setValidity()ãä»ããŠæ€èšŒçµæã«çŽæ¥åœ±é¿ããéåæãã§ãã¯ã®å®è£
ã¯å¥ã®åã³ã§ããã
ã€ãããŒã·ã§ã³ã¯ããã©ãŒãã³ã¹ã«ã圱é¿ããŸããã
å®éãDOMïŒ $parsers ïŒãŸãã¯ã¢ãã«ïŒ $formatters ïŒã§æŽæ°ããããã³ã«ã以åã«æ€èšŒãããŠãã颿°ãèµ·åããããã°ãã°äºãã®å€ã«åœ±é¿ãäžããæ€èšŒãµã€ã¯ã«ãåéããŸããã
æ°ããããŒãžã§ã³ã§ã¯ãã¢ãã«ã倿Žããããã®ã¢ãã«ã«ãšã©ãŒããªãå ŽåïŒ {parse: true ïŒã«ã®ã¿æ€èšŒãéå§ãã{parse: true ã ã¢ãã«èªäœãŸãã¯ããªããŒã¿ãŒå
ã®ã³ã³ãããŒã«ã®è¡šçŸãžã®åœ±é¿ãæé€ãããã¢ããªã±ãŒã·ã§ã³ã®é床ã«ãã©ã¹ã®åœ±é¿ãäžããŸãã
$ãã©ãŒããã¿ãŒããã³$ããŒãµãŒãšã¯äœã§ããããªãäœæãããã®ã§ããïŒ ãããã¯åé€ãããŸããïŒããããåé€ãããŸããã§ããããããã¯ä»ã®ç®çã®ããã®ä»ã®ããŒã«ã§ããããŸã å¿
èŠã§ãã
$formattersãš$parsersã¯ã©ã¡ãããå€ãåãåãããã§ãŒã³ã«æ²¿ã£ãŠæ¬¡ã®ãã³ãã©ãŒé¢æ°ã«æž¡ããã³ãã©ãŒé¢æ°ãå«ãé
åã§ãã ãã§ãŒã³å
ã®åãªã³ã¯ã¯ãå€ã倿ŽããŠããæž¡ãããšãã§ããŸãã
$ãã©ãŒããã¿ãŒ
ã¢ãã«ã倿Žããããã³ã«ã $formattersã¯é
åå
ã®ãã³ãã©ãŒãéã®é åºïŒæ«å°Ÿããå
é ïŒã§$formattersãŸãã æåŸã«æž¡ãããå€ã¯ãDOMã§ã¢ãã«ãã©ã®ããã«è¡šçŸãããããæ±ºå®ããŸãã èšãæãããšã $formattersã¯ngModelCtrl.$modelValueãngModelCtrl.$modelValueã«å€æãããæ¹æ³ãæ
åœããŸãã
$ããŒãµãŒ
ã³ã³ãããŒã«ãDOMããå€ãèªã¿åããã³ã«ã $parsersã¯ãã³ãã©ãŒã®é
åãæåããæåŸãŸã§$parsers ããã§ãŒã³ã«æ²¿ã£ãŠå€ãæž¡ããŸãã æåŸã«æž¡ãããå€ã¯ãã¢ãã«ã§å€ãã©ã®ããã«è¡šçŸãããããæ±ºå®ããŸãã èšãæãããšã $parsersã¯ngModelCtrl.$viewValueãngModelCtrl.$viewValueã«å€æãããæ¹æ³ãæ
åœããŸãã
ã©ãã§äœ¿çšãããŠããŸããïŒ
ãŸã第äžã«ãã¢ã³ã°ã«èªèº«ã圌ã®äœåã§ãããã䜿çšããŠããŸãã ããšãã°ãæå°é·ã®æ€èšŒã䜿çšããŠã³ã³ãããŒã«ãäœæãã $formattersãã§ãã¯ãããšã空ã§ã¯ãªãããDOMããæååã«å€ã倿ããã©ãããŒé¢æ°ãæ¢ã«å«ãŸããŠããããšãããããŸãã
äžèšã®äŸã¯ãå³å¯ã«å®çŸ©ããã圢åŒã§ã®ã¿ã¢ãã«ã«å€ãå
¥ã£ãŠããããšã確èªãããå Žåããã³ãã©ãŒã䜿çšããŠå€ãååŠçïŒãµãã¿ã€ãºïŒããŸãã
ä»ã®2ã€ã®äžè¬çãªäœ¿ç𿹿³ã¯ãå€ã®åæ¹åãã£ã«ã¿ãªã³ã°ïŒããšãã°ããŠãŒã¶ãŒãå
¥åã«ã10,000ããå
¥åããã10000ããã¢ãã«ã«ä¿åããããã®éã®å ŽåïŒãšãã¹ã¯ã®äœæïŒãŠãŒã¶ãŒãé»è©±ãã¹ã¯ã+7ïŒ000 ïŒ000-00-00 "ãããã³ã¢ãã«ã«ä¿åãã" 70000000000 "ïŒã
äŸãããããããã«-äžå¯æ¬ ãªããŒã«ã
 æ€èšŒã¯ä»¥åã©ã®ããã«æ©èœããŸãããïŒå€ãæ€èšŒæ¹æ³ã«é¢ããå
æ¬çãªæ
å ±ã¯ãHabréã«é¢ããæ¬¡ã®èšäºããå
¥æã§ããŸãã
 å°æ¥ãå€ãæ€èšŒæ¹æ³ã䜿çšããªãã®ã¯ãªãã§ããïŒäºå®ã¯ã ndModel.$parsersããundefinedãè¿ãããšã§ãndModel.$parsersã¯ã ngModelCtrl.$modelValueãå
¬ââéãã ngModelCtrl.$modelValueãundefinedã«å
¬éãã ngModelCtrl.$modelValue {parse: false}ãngModelCtrl.$modelValue é害ãã£ãŒã«ãã
ãã®å ŽåãããªããŒã¿ãŒïŒ $validatorsãš$asyncValidators ïŒã¯äœæ¥ãéå§ããŸããã
allowInvalidãã©ã°ãtrueèšå®ããããšã«ããã ngModelOptionsãã®åäœãç¡å¹ã«ã§ãtrue ã
ããŒãžã§ã³1.3ãã ã䟿å©ãªåæããã³éåææ€èšŒã®ããã®ããŒã«ãçšæãããŸããã
ãŸããæ°ããããªããŒã¿ãŒã®äœæ¥ã¯ã¢ãã«ã®æŽæ°ã«é¢ä¿ããŠãããããäžèšã®ngModelOptionsã«ãäŸåããŠããããšã«ãèšåãã䟡å€ããããŸãã
 åæ
åææ€èšŒã®å Žåãæ°ããããŒãžã§ã³ã¯ndModel.$validatorsã³ã¬ã¯ã·ã§ã³ãæäŸããæ€èšŒé¢æ°ã§æ¡åŒµããŸãã
ããªããŒã¿é¢æ°ã¯ãæå¹ãªå€ãšç¡å¹ãªå€ã«å¯ŸããŠããããtrueãŸãã¯falseãè¿ãå¿
èŠããããŸãã
äŸïŒ
  ngModel.$validators.integer = function(modelValue, viewValue) { // ,      if (ctrl.$isEmpty(modelValue)) { return true; } if (INTEGER_REGEXP.test(viewValue)) { return true; //   } return false; //    }; 
éåæ
éåææ€èšŒã®å Žåã¯ã ngModelCtrl.$asyncValidatorsã³ã¬ã¯ã·ã§ã³ã䜿çšãããåãããžãã¯ãæ€èšŒé¢æ°ã§ãããæ¡åŒµããŸãã
éåæããŒãžã§ã³ã®äž»ãªéãïŒ
- éåææ€èšŒã¯ããã¹ãŠã®åææ€èšŒãæå¹ãªå Žåã«ã®ã¿ããªã¬ãŒãããŸã
- ããªããŒã¿ãŒé¢æ°ã¯ãæå¹ãªå€ãšç¡å¹ãªå€ã«å¯ŸããŠããããresolve()ãŸãã¯reject()å®è£
ãããããã¹ã®ã¿ãè¿ãå¿
èŠããããŸãã
AngularJSã®çŽæã¯ãç¹å¥ãªãµãŒãã¹$q ãåºæ¬çã«$q䜿çšãã$q $timeoutã$httpãªã©ã®ãµãŒãã¹ã«ãã£ãŠçæãããŸãã
ãã®ã³ã¬ã¯ã·ã§ã³ã«ã¯ã1ã€ã®ããªããŒã¿ãŒã«ãã£ãŠè¿ãããè€æ°ã®ãããã¹ãå«ãŸããŠããŸããã ã€ãŸããæ€èšŒãæ°ååŒã³åºããšã以åã®ãããã¹ã®çµæã«é¢ä¿ãªããããªããŒã¿ãŒã®æåŸã®åŒã³åºãããã®ãããã¹ã®ã¿ãèæ
®ãããŸãã
ããªããŒã¿ãŒããããã¹ãæž¡ããŠãã解決ãããŸã§ïŒ resolve()ãŸãã¯reject() ïŒã ngModelCtrl.$pendingãã£ãŒã«ãã«ã¯ããªããŒã¿ãŒåãæ ŒçŽããã ngModelCtrl.$valid ngModelCtrl.$invalidããã³ngModelCtrl.$invalidã¯undefined
ãã®æ©èœã«ã¯æ³šæããŠãã ããïŒæ€èšŒãFormCtrl.$errorsãŠããéãFormCtrl.$errorsãã©ãŒã ã¯ç¡å¹ã«ãªããŸããã FormCtrl.$errors Errorsã«ã¯ãšã©ãŒã衚瀺ãããŸãããã FormCtrl.$pendingã¯ãä¿çäžãã®ããªããŒã¿ãFormCtrl.$pending ã
äŸïŒ  ngModelCtrl.$asyncValidators.username = function(modelValue, viewValue) { // ,      if (ctrl.$isEmpty(modelValue)) { return $q.when(); } var def = $q.defer(); //    $timeout(function() { if (usernames.indexOf(modelValue) === -1) { def.resolve(); //  ,   } else { def.reject(); //  ,    } }, 2000); return def.promise; }; ngModelCtrl.$asyncValidators.uniqueUsername = function(modelValue, viewValue) { var value = modelValue || viewValue; // ,     return $http.get('/api/users/' + value). then(function resolved() { //  ,   ,     return $q.reject('exists'); }, function rejected() { //   ,  ,    return true; }); }; 
 å€ä¿®é£Ÿåã䜿çšãããã£ãŒã«ãã§ïŒ $formattersããã³$parsersãä»ããŠïŒéåææ€èšŒãæ
éã«äœ¿çšããããšã¯äŸ¡å€ããããŸããããã«ãããè€æ°ã®æäœãããã³ãã£ãŒã«ãã®èª€ã£ãæ€èšŒãŸãã¯ç¡å¹åãçºçããå¯èœæ§ããããŸãã
ãã®ãããªå Žåã®æ€èšŒäŸ var pendingPromise; ngModelCtrl.$asyncValidators.checkPhoneUnique = function (modelValue) { if (pendingPromise) { return pendingPromise; } var deferred = $q.defer(); if (modelValue) { pendingPromise = deferred.promise; $http.post('/', {value: modelValue}) .success(function (response) { if (response.Result === '   ') { deferred.resolve(); } else { deferred.reject(); } }).error(function () { deferred.reject(); }).finally(function () { pendingPromise = null; }); } else { deferred.resolve(); } return deferred.promise; }; 
 ngMessages
ngMessagesã¢ãžã¥ãŒã«ngMessages ãããŒãžäžã®ã¡ãã»ãŒãžã®è¡šç€ºã容æã«ããããã«èšèšãããŠããŸãã
ãã®ã¢ãžã¥ãŒã«ã¯ããŒãžäžã®ããããã¡ãã»ãŒãžã«äŸ¿å©ã«äœ¿çšã§ãããšããäºå®ã«ãããããããéåžžã¯ãã©ãŒã ã®ãšã©ãŒã衚瀺ããããã«äœ¿çšãããŸãã ãã®ããŒã«ã解決ããåé¡ãçè§£ããããã«ããšã©ãŒã衚瀺ããå€ãæ¹æ³ã®èŠçãèŠãŠããããæ°ãããã®ãšæ¯èŒããŸãããã
æ¯èŒã®äŸãšããŠããã®ãã©ãŒã ã䜿çšããŠã³ã¡ã³ãã远å ããŸãã
 <form name="commentForm"> <ul class="warnings" ng-if="commentForm.$error && commentForm.$dirty"> ... </ul> <label>:</label> <input type="text" name="username" ng-model="comment.username" required> <label>:</label> <textarea name="message" ng-model="comment.message" minlength="5" maxlength="500"></textarea> </form> 
æ€èšŒã®å®è£
ã¯ãã®ãŸãŸã«ããŠãå¿
èŠãªæ¡ä»¶ã«é¢ããã¡ãã»ãŒãžã®è¡šç€ºã®ã¿ãèæ
®ããŸãã
- ååãã£ãŒã«ãã¯ç©ºã«ã§ããŸãã
- ã¡ãã»ãŒãžãã£ãŒã«ãã¯5æå以äžã«ããå¿
èŠããããŸã
- ã¡ãã»ãŒãžãã£ãŒã«ãã¯500æåãè¶
ããããšã¯ã§ããŸãã
 ãšã©ãŒã¯.errorsãããã¯ã«è¡šç€ºãããŸãã
å€ããšã©ãŒè¡šç€ºæ¹æ³
ãã®äŸã¯é·ãåºãŠããã®ã§ãç§ã¯ããããã¿ãã¬ã®äžã«é ããŸãããæ¬¡ã«ããããã®ãã£ãŒã«ãã®ãšã©ãŒã衚瀺ããæ¹æ³ãæ³åããŠãã ããã
 <form name="commentForm"> <ul class="warnings" ng-if="commentForm.$error && commentForm.$dirty"> <span ng-if="commentForm.message.$error.minlength">      5  </span> <span ng-if="commentForm.username.$error.maxlength">      500  </span> <span ng-if="commentForm.username.$error.required">    </span> </ul> <label>:</label> ... <label>:</label> ... </form> 
ãŸããç©äºãããã»ã©æªããªãéããããã§ããïŒ
ãããããªãããã¯ããŒã ã®ã¡ãã»ãŒãžãšã³ã¡ã³ãããã¹ãŠäžåºŠã«è¡šç€ºãããã®ã§ããïŒ é æ¬¡è¡šç€ºã远å ããŠãããä¿®æ£ããŸãããã
 <form name="commentForm"> <ul class="warnings" ng-if="commentForm.$error && commentForm.$dirty"> <span ng-if="commentForm.message.$error.minlength && commentForm.username.$valid">      5  </span> ... </ul> <label>:</label> ... <label>:</label> ... </form> 
ããªãã¯ãŸã ãããã¯ããã»ã©æªããªãããšæããŸããïŒ ããŒãžã®ãã£ãŒã«ãã2ã§ã¯ãªã20ã§ãããããããã«å°ãªããšã5ã€ã®æçš¿ããããšæ³åããŠãã ããã åæ§ã®ã¹ã¿ã€ã«ã§ãç§ãã¡ã®ããŒãžã¯ããã«ç¶æ³ãå€ãããšãŽãç®±ã«å€ãããŸãã
ãã¡ããããã®ã¿ã¹ã¯ãå®è£
ããããã®ãã¹ããã©ã¯ãã£ã¹ã FormControllerã®åäœãæ¡åŒµããç¹å¥ãªãã£ã¬ã¯ãã£ãããã³æŸèæãããFormController ïŒããšãã°ããããžã§ã¯ãã§ã¯ãçŸåšã®ãšã©ãŒãæ ŒçŽãããã¹ãŠã®ã³ã³ãããŒã«ãshowErrorããããã£ã§æ¡åŒµãããŸããïŒ ã
 æ°ãããšã©ãŒè¡šç€ºæ¹æ³
æ¥ç¶ngMesssageså¥ã®ã¢ãžã¥ãŒã«ãšããŠæäŸãããŠãããäœæ¥ãéå§ããåã«æ¥ç¶ããå¿
èŠããããŸãã ããã±ãŒãžãããŒãžã£ãŒã䜿çšããŠã¢ãžã¥ãŒã«ãããŠã³ããŒããŸãã¯ã€ã³ã¹ããŒã«ãããããžã§ã¯ãã«æ¥ç¶ããŸãã
 <script src="path/to/angular-messages.js"></script> 
äŸåãã远å ïŒ
 angular.module('myApp', ['ngMessages']); 
 ãã®ã¢ãžã¥ãŒã«ã®åºæ¬çãªäœæ¥ã¯ã2ã€ã®ãã£ã¬ã¯ãã£ãã䜿çšããããšã§ãã
- ng-messagesãå«ãã³ã³ãã
- ng-messageçŽæ¥- ng-message
ng-messagesã¯ãåŒæ°ãšããŠã ng-messagesããã§ãã¯ããã³ng-messagesãããããŒã®ã³ã¬ã¯ã·ã§ã³ãåãåããŸãããããã®ããŒã¯ãæ¯èŒã®ããã®åŒæ°ãšããŠæååãŸãã¯åŒãåãåããŸãïŒ 1.4ããéå§ïŒã
ã³ã¡ã³ãã远å ããããã®åããã©ãŒã ã®äŸãç¹°ãè¿ããŸããã ngMessagesãŸãã
 <div ng-messages="commentForm.message.$error" class="warnings"> <p ng-message="minlength">      5  </p> <p ng-message="maxlength">      500  </p> <p ng-message="required">    </p> </div> 
ngMessagesã¯èŠçŽ ãšããŠngMessages䜿çšã§ããŸãïŒ
 <ng-messages for="commentForm.message.$error" class="warnings"> <ng-message when="minlength">      5  </ng> <ng-message when="maxlength">      500  </ng> <ng-message when="required">    </ng> </ng-messages> 
ãããã£ãŠã ngMessagesã¯ããã«2ã€ã®åé¡ã解決ããŸããã
- ãªã¹ãã®ãããªèªã¿ãããswitchãªã£ãæ¡ä»¶ããã®éºº
- ã¡ãã»ãŒãžã1ã€ãã€è¡šç€ºããåé¡ã¯ãããèªäœã§è§£æ±ºãããŸãã
ããã«ãã¡ãã»ãŒãžåºåã®åªå
é äœä»ãã®åé¡ã«ã察åŠããŠããŸãã ããã§ã¯ãã¹ãŠãç°¡åã§ããã¡ãã»ãŒãžã¯ãDOMå
ã®å Žæã«åŸã£ãŠè¡šç€ºãããŸãã
è€æ°ã®ã¡ãã»ãŒãžåºåãæå¹ã«ããã«ã¯ã ng-messages-multiple屿§ãng-messages-multipleãã£ã¬ã¯ãã£ãã«è¿œå ãng-messages-multiple ã
 <ng-messages ng-messages-multiple for="commentForm.message.$error"> ... </ng-messages> 
â ngMessages , , , :
, 1.4, 1.31.3 ng-messages-include ng-messages , ng-messages-include ng-message :
1.3
 <ng-messages ng-messages-include="length-message" for="commentForm.message.$error"> </ng-messages> 
1.4+
 <ng-messages for="commentForm.message.$error"> <ng-messages-include="length-message"></ng-messages-include> </ng-messages> 
 (, ) , :
 <script type="script/ng-template" id="length-message"> <ng-message when="minlength">     </ng-message> </script> ... <ng-messages for="commentForm.message.$error"> <ng-messages-include="length-message"></ng-messages-include> </ng-messages> <ng-messages for="anotherForm.someField.$error"> <ng-messages-include="length-message"></ng-messages-include> </ng-messages> 
, , . .
, 1.4 , ng-message-exp :
 // error = {type: required, message: '    '}; <ng-messages for="commentForm.message.$error"> <ng-message-exp="error.type"> {{ error.message }} </ng-message-exp> </ng-messages> 
ng-message-exp , ng-message , ( expression ). , , , AJAX .
â . ng-messages !
:
ã³ã³ãããŒã©ãŒ
bindToController
[]
, controller as , scope .
, this.something . .
:
 app.directive('someDirective', function () { return { scope: { name: '=' }, controller: function () { this.name = 'Foo' }, controllerAs: 'ctrl' ... }; }); 
name .
  $scope.$watch('name', function (newValue) { this.name = newValue; }.bind(this)); 
, , , , ?
1.3 :
bindToController .
 app.directive('someDirective', function () { return { scope: { name: '=' }, controller: function () { this.name = 'Foo' }, bindToController: true, ... }; }); 
ctrl.name $scope.name .
1.4 :
 app.directive('someDirective', function () { return { scope: true, bindToController: { name: '=' }, controller: function () { this.name = 'Foo' }, ... }; }); 
scope bindToController .
, bindToController , , , scope , scope .
- scope , true . bindToController scope .
ãã£ã«ã¿ãŒ
 {{ expression | filter }} 
, , «» ( expression ), ( filter ). , , , .
1.3 : , . , , $digest , , . , , .
plunker
: , , - ? , , «» , ?
ãã®ãããéçïŒ stateless ïŒããã³åçïŒ stateful ïŒãã£ã«ã¿ãŒã®æŠå¿µã¯1.3ã§å°å
¥ãããŸããã ããã©ã«ãã§ã¯ããã£ã«ã¿ãŒã¯statelessããã«åäœããŸãã , $stateful true .
äŸïŒ
 angular.module('myApp', []) .filter('customFilter', ['someService', function (someService) { function customFilter(input) { //     someService input += someService.getData(); return input; } customFilter.$stateful = true; return customFilter; }]); 
é倧ãªå€æŽïŒ
æ³šææ·±ãèªè
ã¯ããã®ãããªå€æŽãå®éã«å€ãåçãã£ã«ã¿ãŒã®åäœãå£ãå¯èœæ§ãããããšã«æ°ä»ããŠãããããããŸããã æ®å¿µãªãããæåã®éšåã§ãã®æ©èœã説æããã®ãå¿ããŠããŸãããããã®ãããªæ©äŒã¯æ€èšãã䟡å€ããããŸãã
dateFilter
weeks
ãããã«
ããã ãã§ã - , .
, .
, markdown. - html.
, , :)
