我正在AngularJS中实现一项功能。 当用户输入1.5时,在视图中,它应显示为01:30,但是当我在控制器中获取此范围值时,它应返回1.5。 我在plunker中添加了代码。请在这里找到。
的index.html:
<!DOCTYPE html>
<html ng-app="wbTimeConverter">
<head>
<link rel="stylesheet" href="style.css">
<script src="https://code.angularjs.org/1.5.8/angular.js"></script>
<script src="script.js"></script>
<script src="wbNumberToTime.js"></script>
</head>
<body ng-controller="AppController">
<h1>Hello Plunker!</h1>
<input type="text" md-maxlength="5" wb-number-to-time-convert ng-model="task" placeholder="task" ng-blur="onDataChange();" />
<input type="text" md-maxlength="5" wb-number-to-time-convert ng-model="project" placeholder="project" ng-blur="onDataChange();" />
<br>
<label>Task : {{task}}</label><br>
<label>Project : {{project}}</label><br>
<label>TotalResult : {{totalHours}}</label>
</body>
</html>
控制器 - Script.js
var app = angular.module('wbTimeConverter', []);
app.controller('AppController', function($scope) {
$scope.onDataChange = onDataChange;
function onDataChange(){
console.log("res");
$scope.totalHours= parseFloat($scope.task) + parseFloat($scope.project, 10);
}
});
指令:
// 'use strict';
// /**
// * This directive is convert number into hours and minutes format-HH:MM
// * This will trigger when we change value in input element and gives respective value in time format
// */
app.directive('wbNumberToTimeConvert', function ($filter, $browser) {
return {
require: 'ngModel',
link: function ($scope, $element, $attrs, ngModelCtrl) {
var listener = function () {
var value = $element.val();
var result = convertToTime(value);
$element.val(result.timeFormat);
$element.attr('attr-hrs', result.decimalFormat);
};
// This runs when we update the text field
ngModelCtrl.$parsers.push(function (viewValue) {
return viewValue;
});
$element.bind('change', listener);
$element.bind('keydown', function (event) {
var key = event.keyCode;
// FIXME to handle validations
});
$element.bind('paste cut', function () {
$browser.defer(listener);
});
function convertToTime(value) {
var res = { 'timeFormat': '', 'decimalFormat': '' };
var inputValue = value;
if (inputValue.indexOf(':') > -1) {
inputValue = convertToNumberFormat(inputValue);
res.decimalFormat = inputValue;
} else {
res.decimalFormat = value;
}
inputValue = inputValue.split('.');
var hoursValue = inputValue[0];
if (inputValue.length > 1) {
var hrs = parseInt(hoursValue, 10);
hrs = isNaN(hoursValue) ? 0 : hrs;
hrs = (hrs < 10) ? '0' + hrs : hrs;
var minutesValue = inputValue[1];
var mins = parseInt(minutesValue, 10);
mins = (minutesValue.length < 2 && (mins < 10)) ? Math.round(mins * 6) : Math.round(mins * 0.6);
mins = (mins < 10) ? ('0' + mins) : mins;
inputValue = hrs + ':' + mins;
res.timeFormat = inputValue;
} else {
inputValue = (parseInt(inputValue, 10) < 10) ? '0' + parseInt(inputValue, 10) : parseInt(inputValue, 10);
inputValue = inputValue + ':' + '00';
res.timeFormat = inputValue;
}
return res;
}
function convertToNumberFormat(inputValue) {
var timeValue = inputValue.split(':');
var hours = parseInt(timeValue[0], 10);
var mins = parseInt(timeValue[1], 10);
if (isNaN(hours)){
hours = '00';
}
if (isNaN(mins)) {
mins = '00';
}
mins = Math.round(mins / 0.6);
if (mins < 10) {
mins = '0' + mins;
}
var number = hours + '.' + mins;
return number;
}
}
};
});
以下是plunker链接: https://plnkr.co/edit/76lwlnQlGC0wfjixicCK?p=preview
在文本框模糊时,在第一次和第二次在文本框中模糊时,它在View和Controller中的值不同,它在视图和控制器中显示相同的值01:30。我该如何解决?
答案 0 :(得分:1)
您可以将输入保留在ng-model myValue
中并调用函数format(value)
以显示您需要的内容
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.myValue = "1.5";
$scope.format = function(value) {
var hrs = parseInt(Number(value));
var min = Math.round((Number(value) - hrs) * 60);
return hrs + ':' + min;
}
});
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
<input type="text" ng-model="myValue">
<br>Formatted Value : {{format(myValue)}}
<br>Base value : {{myValue}}
</div>
&#13;
答案 1 :(得分:1)
使用指令真的很容易!以此为例:JSFiddle
如果你有一个需要ngModelController的指令,你可以很容易地操作viewValue。
ngModelController有两个我们感兴趣的属性,$ modelValue和$ viewValue。 $ modelValue是您在作用域上使用的值,$ viewValue是用户看到的值。
ngModelController还有一个属性$ formatters,它是一个将modelValue转换为viewValue的格式化程序数组。因此,如果modelValue在控制器一侧发生变化,它将通过格式化程序直到结束,这将改变viewValue。如果您想创建自己的格式化程序,只需将其添加到数组中即可!
//This formatter will convert the modelValue to display as uppercase in the viewValue
ngModelController.$formatters.push(function(modelValue) {
if (modelValue) {
return modelValue.toUpperCase();
}
});
但$ formatters属性仅适用于modelValue发生更改的情况,因此如果用户在输入字段中输入内容,则viewValue会发生变化,处理此问题的最简单方法是附加到onBlur事件中我们将使用ngModel控制器提供的另一个函数来更改viewValue。 $ setViewValue(value)将更改viewValue。如果更改指令中的viewValue,视图将不会自动更新,因此您需要调用ngModelController提供的$ render函数
element.on('blur', function() {
ngModelController.$setViewValue(convertDoubleToTimeString(ngModelController.$modelValue));
ngModelController.$render();
});
有关此内容的详情,请参阅this。
编辑:
在这个例子中,我没有编写一个将viewValue(1:30)转换为modelValue(1,5)的解析器。所以我们加一个。我也有一个updated JSFiddle
ngModelController.$parsers.unshift(function(viewValue) {
if (viewValue && viewValue.indexOf(':') < 0) {
return viewValue;
} else {
return convertTimeStringToDouble(viewValue)
}
});
将解析器解析到$ parsers数组意味着它将是第一个执行的解析器,这不是必需的,但为什么不呢,嗯?
当viewValue发生更改时,还有其他方法可以不更改modelValue,但这个方法是最正确的。
另一种方法是直接设置$ viewValue而不通过$ setViewValue()。
//ngModelController.$setViewValue(ngModelController.$modelValue.toUpperCase());
ngModelController.$viewValue = ngModelController.$modelValue.toUpperCase();
在最后一行中,它不会经历通过所有解析器和验证器的常规步骤,因此这是不太理想的解决方案。
答案 2 :(得分:0)
你可以在控制器中声明一个函数来返回calucalted值,在html中你可以调用该函数并传递范围变量。
$scope.calculate = function(value){
var calculatedValue = /*Your operation*/;
return calculatedValue;
}
<input type="text" ng-model="value"\>
<p>{{calculate(value)}}</p>
如果您想要相对于输入值实时更新计算值,那么您可以使用另一个范围变量来存储计算值。
$scope.calculate = function(value){
$scope.calculatedValue = /*Your operation*/;
}
<input type="text" ng-model="value" ng-change="calculate(value)"\>
<p>{{calculatedValue}}</p>