如何在AngularJS中以不同方式显示模型和视图

时间:2016-12-14 13:28:16

标签: angularjs angularjs-ng-repeat angular-material

我正在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。我该如何解决?

3 个答案:

答案 0 :(得分:1)

您可以将输入保留在ng-model myValue中并调用函数format(value)以显示您需要的内容

&#13;
&#13;
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;
&#13;
&#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>