How to show the model and see it differently in AngularJS

I am implementing functionality in AngularJS. When the user enters 1.5, In view, it should be displayed as 01:30, but when I get this value in the controller, it should be returned as 1.5. I added the code to the plunker. Please find here.

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> 

Controller - 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); } }); 

directive:

 // '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; } } }; }); 

Here is the plunker link: https://plnkr.co/edit/76lwlnQlGC0wfjixicCK?p=preview

In blurring the text field, it works fine in the "View" and "Controller" modes for the first time and the second time it is blurred in the text field, it shows the same value 01:30 in both the view and the controller. How can I solve it?

+5
source share
3 answers

You can save your input in ng-model myValue and call the format(value) function to display what you need

 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; } }); 
 <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> 
+1
source

It is very simple using the directive! Take this as an example: JSFiddle

If you have a directive requiring ngModelController, you can easily manipulate viewValue.

ngModelController has two properties that interest us: $ modelValue and $ viewValue. $ modelValue is the value you use in scope, and $ viewValue is the one that the user sees.

ngModelController also has a $ formatters property, which is an array of formatters that convert modelValue to viewValue. Therefore, if the modelValue variable changes on the controller side, it will go through the formatter to the end, and this will change the viewValue. If you want to create your own formatter, just add it to the array!

 //This formatter will convert the modelValue to display as uppercase in the viewValue ngModelController.$formatters.push(function(modelValue) { if (modelValue) { return modelValue.toUpperCase(); } }); 

but the $ formatters property only works when the modelValue parameter changes, so if the user enters something into the input field, the viewValue variable changes, the easiest way to handle this is to attach to the onBlur event, in which we will change the viewValue using another function provided by the ngModel controller. $ setViewValue (value) will change viewValue. If you change the viewValue in the directive, the view will not be automatically updated, so you need to call the $ rendering function provided by ngModelController

 element.on('blur', function() { ngModelController.$setViewValue(convertDoubleToTimeString(ngModelController.$modelValue)); ngModelController.$render(); }); 

For more information about this, you can read this .

EDIT:

In this example, I did not write a parser that converts viewValue (1:30) to modelValue (1,5). So add one. I also have updated JSFiddle

 ngModelController.$parsers.unshift(function(viewValue) { if (viewValue && viewValue.indexOf(':') < 0) { return viewValue; } else { return convertTimeStringToDouble(viewValue) } }); 

The cancellation of parsers on the $ parsers array means that it will be executed first, this is not necessary, but why not, and ??

There are other ways to not change modelValue when changing viewValue, but this is the most correct option.

An alternative would be to simply set $ viewValue directly without going through $ setViewValue ().

 //ngModelController.$setViewValue(ngModelController.$modelValue.toUpperCase()); ngModelController.$viewValue = ngModelController.$modelValue.toUpperCase(); 

In this last line, it will not go through the usual steps going through all the parsers and validators, so this is a less ideal solution.

+1
source

You can declare a function in the controller to return the calucalted value, and in html you can call this function and pass the scope variable.

 $scope.calculate = function(value){ var calculatedValue = /*Your operation*/; return calculatedValue; } <input type="text" ng-model="value"\> <p>{{calculate(value)}}</p> 

If you want to update the calculated value in real time with respect to the input value, you can use another scope variable to store the calculation value.

 $scope.calculate = function(value){ $scope.calculatedValue = /*Your operation*/; } <input type="text" ng-model="value" ng-change="calculate(value)"\> <p>{{calculatedValue}}</p> 
0
source

Source: https://habr.com/ru/post/1261268/


All Articles