0

У меня есть директива, которая имеет маску и проверку для управления вводом. Это в основном ввод времени, когда пользователь может вводить что-то вроде 45 (45 минут) или 2,5 (2,5 часа => 150 минут). Ввод - type=number при редактировании, но type=text при отображении результата с использованием фильтра.Маска ввода AngularJS с проверкой

(только с шагом по 15 минут допускается, и применяется фильтр на событие размытия)

Все работает отлично, за исключением, что начальное значение, когда я нажимаю в текстовое поле, теряется. В событии focus значение scope.minutes не определено, где это должно быть значение 90, установленное в контроллере. Я не могу понять, почему.

angular.module('demoApp', []) 
 
\t .controller('MainController', MainController) 
 
    .filter("hoursMinutes", function() { 
 
      return function (mins) { 
 
       if (mins == 0) return "0 mins"; 
 
       var hours = ((mins - (mins % 60))/60); 
 
       var minutes = (mins % 60); 
 
       return (hours > 0 ? hours + " hr" + (hours === 1 ? "" : "s") : "") + (minutes > 0 ? " " + minutes + " min" + (minutes === 1 ? "" : "s") : ""); 
 
      } 
 
     }) 
 
    .directive("ixTimeEntry", function ($filter) { 
 
      return { 
 
       restrict: "A", 
 
       require: 'ngModel', 
 
       scope: { 
 
        minutes: "=", 
 
        filter: "@", 
 
        inputFormat: "@" 
 
       }, 
 
       link: function (scope, element, attr, ngModel) { 
 
        
 
        // could set a max attribute, so mins can't be more than 1440 (a day)? 
 

 
        var inputFormat = scope.inputFormat || "minutes"; 
 
        var filter = scope.filter || "hoursMinutes"; 
 

 
        // for DOM -> model validation 
 
        ngModel.$parsers.unshift(function (value) { 
 
         var result = validate(value); 
 
         ngModel.$setValidity('ixTimeEntry', result.valid); 
 
         return result.value; 
 
        }); 
 

 
        // for model -> DOM validation 
 
        ngModel.$formatters.unshift(function (value) { 
 
         ngModel.$setValidity('ixTimeEntry', true); 
 
         return $filter(filter)(value); 
 
        }); 
 

 
        function validate(input) { 
 
         var result = { valid: false, value: input }; 
 
         if (input === undefined) return result; 
 
         input = +input; 
 
         if (input === 0) return result; 
 
         if (input < 0) return result; 
 

 
         if (inputFormat === "minutes") { 
 
          // entering as minutes: 
 
          // if 15, 30, 45, 60, 75, 90, etc  => treat as minutes 
 
          // if .25, .5, .75, 1, 1.25, ...12  => treat as hours 
 
          // else (e.g. 13, 14, 16, 17, 18, etc) => invalid 
 
          if (input % 15 === 0) result = { valid: true, value: input }; 
 
          if (input % .25 === 0 && input <= 12) result = { valid: true, value: input * 60 }; 
 
         } else if (inputFormat === "hours") { 
 
          // entering as hours: 
 
          // if .25, .5, .75, 1, 1.25, etc  => treat as hours 
 
          // else         => invalid 
 
          if (input % .25 === 0) result = { valid: true, value: input * 60 }; 
 
         } else { 
 
          throw "Invalid inputFormat in timeEntry"; 
 
         } 
 

 
         return result; 
 
        } 
 

 
        function addMask(text) { 
 
         return $filter(filter)(text); 
 
        } 
 

 
        function removeMask(text) { 
 
         if (inputFormat === "hours") 
 
          return +text/60; 
 
         return text; 
 
        } 
 

 
        element.val(addMask(scope.minutes)); 
 

 
        element.bind("blur", function() { 
 
         element.attr("type", "text"); 
 
         scope.$apply(function() { 
 
          var value = validate(element.val()).value; 
 
          scope.minutes = value; 
 
          element.val(addMask(value)); 
 
         }); 
 
        }); 
 

 
        element.bind("focus", function() { 
 
         element.attr("type", "number"); 
 
         scope.$apply(function() { 
 
          element.val(removeMask(scope.minutes)); 
 
         }); 
 
        }); 
 
       } 
 
      }; 
 
     });; 
 

 

 
function MainController() { 
 
\t var vm = this; 
 
    vm.minutes1 = 90; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> 
 

 
<div ng-app="demoApp" ng-controller="MainController as vm"> 
 
<form id="timeForm" name="timeForm" > 
 
<input type="text" class="form-control" name="time" placeholder="time" ix-time-entry input-format="minutes" minutes="vm.minutes" filter="hoursMinutes" ng-required="true" ng-model="vm.minutes1" /> 
 
</form> 
 
<br> 
 
Model: {{vm.minutes1}}<br> 
 
Valid: {{timeForm.time.$valid}}<br> 
 
</div>

ответ

1

Вы только установить vm.minutes1 = 90; в вашем MainController. Он работает, если вы установили vm.minutes = 90;.

angular.module('demoApp', []) 
 
\t .controller('MainController', MainController) 
 
    .filter("hoursMinutes", function() { 
 
      return function (mins) { 
 
       if (mins == 0) return "0 mins"; 
 
       var hours = ((mins - (mins % 60))/60); 
 
       var minutes = (mins % 60); 
 
       return (hours > 0 ? hours + " hr" + (hours === 1 ? "" : "s") : "") + (minutes > 0 ? " " + minutes + " min" + (minutes === 1 ? "" : "s") : ""); 
 
      } 
 
     }) 
 
    .directive("ixTimeEntry", function ($filter) { 
 
      return { 
 
       restrict: "A", 
 
       require: 'ngModel', 
 
       scope: { 
 
        minutes: "=", 
 
        filter: "@", 
 
        inputFormat: "@" 
 
       }, 
 
       link: function (scope, element, attr, ngModel) { 
 
        
 
        // could set a max attribute, so mins can't be more than 1440 (a day)? 
 

 
        var inputFormat = scope.inputFormat || "minutes"; 
 
        var filter = scope.filter || "hoursMinutes"; 
 

 
        // for DOM -> model validation 
 
        ngModel.$parsers.unshift(function (value) { 
 
         var result = validate(value); 
 
         ngModel.$setValidity('ixTimeEntry', result.valid); 
 
         return result.value; 
 
        }); 
 

 
        // for model -> DOM validation 
 
        ngModel.$formatters.unshift(function (value) { 
 
         ngModel.$setValidity('ixTimeEntry', true); 
 
         return $filter(filter)(value); 
 
        }); 
 

 
        function validate(input) { 
 
         var result = { valid: false, value: input }; 
 
         if (input === undefined) return result; 
 
         input = +input; 
 
         if (input === 0) return result; 
 
         if (input < 0) return result; 
 

 
         if (inputFormat === "minutes") { 
 
          // entering as minutes: 
 
          // if 15, 30, 45, 60, 75, 90, etc  => treat as minutes 
 
          // if .25, .5, .75, 1, 1.25, ...12  => treat as hours 
 
          // else (e.g. 13, 14, 16, 17, 18, etc) => invalid 
 
          if (input % 15 === 0) result = { valid: true, value: input }; 
 
          if (input % .25 === 0 && input <= 12) result = { valid: true, value: input * 60 }; 
 
         } else if (inputFormat === "hours") { 
 
          // entering as hours: 
 
          // if .25, .5, .75, 1, 1.25, etc  => treat as hours 
 
          // else         => invalid 
 
          if (input % .25 === 0) result = { valid: true, value: input * 60 }; 
 
         } else { 
 
          throw "Invalid inputFormat in timeEntry"; 
 
         } 
 

 
         return result; 
 
        } 
 

 
        function addMask(text) { 
 
         return $filter(filter)(text); 
 
        } 
 

 
        function removeMask(text) { 
 
         if (inputFormat === "hours") 
 
          return +text/60; 
 
         return text; 
 
        } 
 

 
        element.val(addMask(scope.minutes)); 
 

 
        element.bind("blur", function() { 
 
         element.attr("type", "text"); 
 
         scope.$apply(function() { 
 
          var value = validate(element.val()).value; 
 
          scope.minutes = value; 
 
          element.val(addMask(value)); 
 
         }); 
 
        }); 
 

 
        element.bind("focus", function() { 
 
         element.attr("type", "number"); 
 
         scope.$apply(function() { 
 
          element.val(removeMask(scope.minutes)); 
 
         }); 
 
        }); 
 
       } 
 
      }; 
 
     });; 
 

 

 
function MainController() { 
 
\t var vm = this; 
 
    vm.minutes = 90; 
 
    vm.minutes1 = 90; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> 
 

 
<div ng-app="demoApp" ng-controller="MainController as vm"> 
 
<form id="timeForm" name="timeForm" > 
 
<input type="text" class="form-control" name="time" placeholder="time" ix-time-entry input-format="minutes" minutes="vm.minutes" filter="hoursMinutes" ng-required="true" ng-model="vm.minutes1" /> 
 
</form> 
 
<br> 
 
Model: {{vm.minutes1}}<br> 
 
Valid: {{timeForm.time.$valid}}<br> 
 
</div>

+0

Ого. Такая ошеломляющая опечатка. Спасибо, Андрей! – Sean

Смежные вопросы