AngularJS directive is breaking based on first character of directive name -


i wrote angular directive exhibiting strange behavior. directive adds function $parsers limit user types based on regex pattern. if current text doesn't match patter, parser reverts text previous value of field.

as result, when text reverted, angular detects change in field value , enters parser again. fine since value passed parser valid experiencing 1 strange quirk.

after got directive working decided change name. did , validation failing. error-handler reporting recursion. when debugged code found 2nd call parser after entering invalid character showed field value parameter 'undefined'. result, code treated value invalid , tried revert again, caused call parser 'undefined' value, etc, etc until stack overflow occurred.

i changed directive name back, debugged again, , started working fine! second call parser had correct value instead of 'undefined'.

i did little playing around , discovered recreate bug altering first character of directive name. directive names began characters 'a' through 'm' worked fine, names beginning 'n' through 'z' broke (ok, confess, didn't try 26 characters, sampling of characters showed names in sample first letter of directive name in first half of alphabet worked , runs first letter in 2nd half of alphabet failed).

i put plunker code demonstrate it:

http://plnkr.co/edit/k8hpk2jsmcs6xjokies5

var app = angular.module('plunker', []);  app.controller('mainctrl', function($scope) {     $scope.somenumber; });  app.directive('formattedwithpattern', function () {     // formats input field positive integer.     // usage:     //  <input type="text" data-integer-format>     // creates:     //  <input type="text" data-integer-format>     return {         require: 'ngmodel',         link: function (scope, element, attr, ctrl) {             if (!ctrl) return;              var pattern = attr.ngpattern;             // pattern between slashes , modifiers             var r = new regexp("^/(.*)/(.*)$");             var matches = r.exec(pattern);             var regex;             if (matches) {                 regex = new regexp('^' + matches[1] + '$', matches[2]);             }             var lasttext = '';             var reverted = false;              function fromuser(text) {                 var m = regex.exec(text);                 if (m) {                     // join matches single string                     lasttext = m[0];                     if (lasttext != text) {                         // original text contained invalid characters                         ctrl.$setviewvalue(lasttext);                         ctrl.$render();                     }                 }                 else {                     // nothing in text matched regular expression...                     // revert last value                     if (text != lasttext) {                         ctrl.$setviewvalue(lasttext);                         ctrl.$render();                     }                 }                 return lasttext;             }              ctrl.$parsers.unshift(fromuser);         }     }; }); 

here's example of in use (also plunker):

<body ng-controller="mainctrl">     <input type="text" name="testnumber" id="testnumber"         data-ng-model="somenumber" data-ng-required="true"        ng-pattern="/[\+\-]?[0-9]*(\.[0-9]*)?/"         formatted-with-pattern />     {{zip}} </body> 

for reason, plunker behaves differently saw when testing on computer. failures still in upper range of alphabet, failures start @ 'o' instead of 'n'.

if change name of directive in app.js , index.html begin character 'o' through 'z' , rerun plunker can see behavior. above directive using numeric pattern, when directive name "valid" directive doesn't allow characters other 0-9, ., +, , -. when name "invalid" directive allows characters because recursive call parser breaking out without changing input field value.

this strikes me bizarre behavior. didn't find other mentions of online thought i'd throw out here. has else ever encountered this? bug in angularjs? know work-around other making sure directive name begins character through m?

you raise directive priority: ensure execution order this:

return {   require: 'ngmodel',   priority: 1, // default 0   link: function (scope, element, attr, ctrl) {     ...   } }; 

it ensure directive postlink function run after ng-required , ng-pattern.

example plunker: http://plnkr.co/edit/dy1zcq9f8eejywo1m4oe?p=preview

you use ctrl.$viewvalue directly avoid directive execution order problem.

actually, imho, make more sense use ctrl.$viewvalue since re-render view if invalid, need real view value, not value passed other parsers.

to so, change parser from:

function fromuser(text) {   ... } 

to instead:

function fromuser() {   var text = ctrl.$viewvalue;   ... } 

example plunker: http://plnkr.co/edit/fa2fq4anlurcdumoopux?p=preview

hope helps.


Comments

Popular posts from this blog

javascript - Jquery show_hide, what to add in order to make the page scroll to the bottom of the hidden field once button is clicked -

javascript - Highcharts multi-color line -

javascript - Enter key does not work in search box -