Angular $viewValue 不反映在更改事件的文本框中
Angular $viewValue doesn't reflect in textbox on change event
我正在尝试实现 INR(印度卢比)到 USD(美元)的货币转换器。该视图应始终显示以 INR 为单位的值。但该模型应以美元计价。
为此,我实现了一个用于输入的文本框。输入将始终以 INR 形式给出。
我正在使用 ngModel 的 $viewValue 和 $modelValue 属性来处理我的问题。
我的情况是,在某些事件中,货币是在后台计算的。例如。如果货币在模型中存储为 1 美元。它在应用程序中的某些事件中变为 2 美元。在这种情况下,我的视图以美元显示价值(在本例中为 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
演示
出于演示目的,我故意在 2 秒后使用 $timeout
更改了模型值。
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>
我正在尝试实现 INR(印度卢比)到 USD(美元)的货币转换器。该视图应始终显示以 INR 为单位的值。但该模型应以美元计价。
为此,我实现了一个用于输入的文本框。输入将始终以 INR 形式给出。
我正在使用 ngModel 的 $viewValue 和 $modelValue 属性来处理我的问题。
我的情况是,在某些事件中,货币是在后台计算的。例如。如果货币在模型中存储为 1 美元。它在应用程序中的某些事件中变为 2 美元。在这种情况下,我的视图以美元显示价值(在本例中为 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
演示
出于演示目的,我故意在 2 秒后使用 $timeout
更改了模型值。
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>