javascript - Angular $viewValue 未反射(reflect)在更改事件的文本框中

标签 javascript angularjs angular-ngmodel angular-directive

我正在尝试实现 INR(印度卢比)到 USD(美元)的货币转换器。 View 应始终显示以 INR 为单位的值。但该模型应保存美元值(value)。

为此,我实现了一个用于输入的文本框。输入始终以 INR 为单位。

我正在使用 ngModel 的 $viewValue 和 $modelValue 属性来处理我的问题。

我遇到了一种情况,货币是在某些事件的后台计算的。例如。如果货币在模型中存储为 1 美元。在应用程序中的某些事件中,它会更改为 2 美元。在这种情况下,我的 View 显示以美元为单位的值(在本例中为 2 美元),并且仅当我关注文本框时,该值才会以 INR 为单位显示(如 126 INR)。

$viewValue 未在更改事件的文本框中显示。

请帮助我。

.directive('usdInrInput', function($filter, $timeout) {
    return {
        require: 'ngModel',
        link: function(scope, element, attrs, modelCtrl) {

            function conversionFunction() {
                modelCtrl.$viewValue = modelCtrl.$modelValue * 63;
                modelCtrl.$render();
            }
            element.bind("focus", function(e) {
                $timeout(function() {
                    conversionFunction();
                }, 0);
            });
            element.bind("change", function(e) {
                $timeout(function() {
                    conversionFunction();
                }, 0);
            });
            modelCtrl.$parsers.push(function(inputValue) {
                var changedOutput = parseInt(inputValue) / 63;
                modelCtrl.$setViewValue(parseInt(inputValue));
                modelCtrl.$render();
                return parseInt(changedOutput);
            });
        }
    };
})

最佳答案

您应该使用 scope.$watch 监视模型值的变化,如下所示:

scope.$watch(function() {
    return modelCtrl.$modelValue;
}, function(val) {
    conversionFunction();
});  
  • 使用美元汇率常量,以便在发生变化时可以在一处进行修改。

  • 使用 $evalAsync 而不是 $timeout(function(){},0)

引用evalAsync vs timeout

演示

出于演示目的,我故意使用 $timeout 在 2 秒后更改了模型值。

angular
  .module('myApp', []);
angular
  .module('myApp')
  .controller('MyController', MyController)
  .directive('usdInrInput', usdInrInput);
MyController.$inject = ['$scope', '$timeout'];

function MyController($scope, $timeout) {
  $scope.inr = 630;
  $timeout(function() {
    $scope.inr = 10;
  }, 2000);
}

usdInrInput.$inject = ['$filter', '$timeout'];

function usdInrInput($filter, $timeout) {
  return {
    require: 'ngModel',
    link: function(scope, element, attrs, modelCtrl) {
      var cRate = 63;
      scope.$watch(function() {
        return modelCtrl.$modelValue;
      }, function(val) {
        conversionFunction();
      });

      function conversionFunction() {
        modelCtrl.$viewValue = modelCtrl.$modelValue * cRate;
        modelCtrl.$render();
      }
      element.bind("focus", function(e) {
        scope.$evalAsync(function() {
          conversionFunction();
        });
      });
      element.bind("change", function(e) {
        scope.$evalAsync(function() {
          conversionFunction();
        });
      });
      modelCtrl.$parsers.push(function(inputValue) {
        var changedOutput = parseInt(inputValue) / cRate;
        modelCtrl.$setViewValue(changedOutput);
        modelCtrl.$render();
        return changedOutput;
      });
    }
  };
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js"></script>

<div ng-app="myApp" ng-controller="MyController as MC">

  <input type="text" ng-model="inr" usd-inr-input> {{inr}}
</div>

关于javascript - Angular $viewValue 未反射(reflect)在更改事件的文本框中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42825677/

相关文章:

javascript - 使用 mongoose 更新许多属性的优雅方式

javascript - 我怎样才能实现 $ ('input' ).on ('change' , function() AngularJS

javascript - 使用 angularJS ng-repeat 和 ng-model 进行动态多列过滤

javascript - 奇数斐波那奇数之和因较高值而失败?

javascript - TypeScript - 将对象文字传递给类构造函数

angularjs - 问号在 Angular 隔离范围绑定(bind)中有什么作用?

javascript - 如何使用 Angular promise 作为字符串的一部分

javascript - 在 AngularJS 中的 ng-model 上定义一个空值

javascript - 具有可以未定义的参数的 Angular getter/setter

javascript - 如何解决nodejs uncaughtException : Connection already released error and MaxListenersExceededWarning?