2015-08-01 13 views
0

У меня есть несколько полей формы, которые необходимо отобразить в USD ($ n.nn), и успешно использовали специальную валютную директиву. Но я добавил NgModelOptions контролировать дребезг:NgModelOptions + Currency Filter = Поле не отображает модель

{ updateOn: 'default blur', debounce: { 'default':100, 'blur': 0 } }"

Это работает отлично, за исключением, когда поле обновляется затем быстро вышел, и в этом случае предыдущих дисплеев значения. Ввод, а затем выход из поля, приведет к отображению правильного значения.

Любые идеи о том, как объединить директиву или валютный фильтр с NgModelOptions, чтобы отображаемое значение отражало значение модели при выходе?

Вот текущая директива:.

.directive('ngCurrency', function ($filter, $locale) { 
     return { 
     require: 'ngModel', 
     scope: { 
      min: '=min', 
      max: '=max', 
      ngRequired: '=ngRequired' 
     }, 
     link: function (scope, element, attrs, ngModel) { 

      function decimalRex(dChar) { 
      return RegExp("\\d|\\" + dChar, 'g'); 
      } 

      function clearRex(dChar) { 
      return RegExp("((\\" + dChar + ")|([0-9]{1,}\\" + dChar + "?))&?[0-9]{0,2}", 'g'); 
      } 

      function decimalSepRex(dChar) { 
      return RegExp("\\" + dChar, "g"); 
      } 

      function clearValue(value) { 
      value = String(value); 
      var dSeparator = $locale.NUMBER_FORMATS.DECIMAL_SEP; 
      var clear = null; 

      if (value.match(decimalSepRex(dSeparator))) { 
       clear = value.match(decimalRex(dSeparator)) 
         .join("").match(clearRex(dSeparator)); 
       clear = clear ? clear[0].replace(dSeparator, ".") : null; 
      } 
      else if (value.match(decimalSepRex("."))) { 
       clear = value.match(decimalRex(".")) 
         .join("").match(clearRex(".")); 
       clear = clear ? clear[0] : null; 
      } 
      else { 
       clear = value.match(/\d/g); 
       clear = clear ? clear.join("") : null; 
      } 

      return clear; 
      } 

      ngModel.$parsers.push(function (viewValue) { 
      cVal = clearValue(viewValue); 
      return parseFloat(cVal); 
      }); 

      element.on("blur", function() { 
      element.val($filter('currency')(ngModel.$modelValue)); 
      scope.$apply(); 
      }); 

      ngModel.$formatters.unshift(function (value) { 
      return $filter('currency')(value); 
      }); 

      scope.$watch(function() { 
      return ngModel.$modelValue; 
      }, function (newValue, oldValue) { 
      runValidations(newValue); 
      }); 

      function runValidations(cVal) { 
      if (!scope.ngRequired && isNaN(cVal)) { 
       return; 
      } 
      if (scope.min) { 
       var min = parseFloat(scope.min); 
       ngModel.$setValidity('min', cVal >= min); 
      } 
      if (scope.max) { 
       var max = parseFloat(scope.max); 
       ngModel.$setValidity('max', cVal <= max); 
      } 
      } 
     } 
     } 
    }) 
+0

Дополнительная информация была бы замечательной. Возможно, код вашего фильтра и как вы отображаете значение поля? –

+1

@ Итмар - да, я не стал много продолжать. Я думаю, что это связано с фильтром/директивой, рассматривающим $ modelValue перед обновлением. Я исправлю вопрос, включив эту директиву. – JoeyR

ответ

0
element.on("blur", function() { 
     element.val($filter('currency')(ngModel.$modelValue)); 
     scope.$apply(); 
     }); 

Что я предполагаю, что происходит, что вы меняете поле и оставить его, что вызывает цикл дайджеста для запуска - и что делает сферу $ apply() внутри вашего обратного вызова, попробуйте выполнить, пока он уже выполняется. Обходной путь к этому обычно заключается в том, чтобы обернуть весь вызов в $ timeout.

element.on("blur", function() { 
     $timeout(function() { 
      element.val($filter('currency')(ngModel.$modelValue)); 
      scope.$apply(); 
     }); 
     }); 

Я уверен, что когда это произойдет, консоль отобразит какое-то сообщение об ошибке - для дальнейшего использования.

Есть ли причина, по которой вы не используете фильтр непосредственно на модели, например: {{my.model | currency}} вместо добавления события? Похоже на плохую практику.

+0

Ошибка не генерируется. Я не могу поместить фильтр в модель, поскольку я работаю с текстовым полем для отображения и числовым значением в модели. Я готов принять совершенно другой подход, если это необходимо, но мне нужен дисплей валюты и числовое значение на задней панели. – JoeyR

+0

Ваш предлагаемый код действительно имеет значение: Непринятый ReferenceError: $ timeout не определен, но я разделяю ваше мнение о том, что проблема заключается в этом разделе. Модель ngModel. $ ModelValue вытаскивает предварительно обновленное значение, так как модель не обновляется до тех пор, пока угловые процессы не размываются, что происходит после возникновения события DOM. Вопрос в том, где я могу получить значение до обновления? – JoeyR

+0

Вам нужно ввести $ compile ... то же место, где вы ввели $ filter и $ locale: '.directive ('ngCurrency', function ($ filter, $ locale, $ compile) {' –

Смежные вопросы