条件ng-需要集体检查3个输入框不起作用

时间:2017-07-19 12:10:48

标签: javascript angularjs forms

Angular v 1.6.8

我有一个带有3个输入框的表单,用户输入数字,我的要求是其中一个输入框必须至少有一些值(大于0),但这不起作用。

我为所有3个输入框绑定一个带ng-required的方法,此方法检查所有3个输入框值,其值为 true / false 。在这个方法中,我使用原生的javascript方法.some()来检查是否有任何一个输入框的值大于0而不是输入框的其余部分(即ng-required被评估为false)

我还添加了一个指令来控制输入框的最大值和最小值。

现在我的问题是

1。当用户为所有3个输入框输入0时,表单变为有效,这是不正确的。 (这是我的主要问题)
  2. 如果我在输入框中输入的值超过最大值,那么指令会正确地给出验证错误但是也会使用$ parse键($error": { "validRange": true, "parse": true }))?为什么会这样?

3。所有错误消息一起出现,这不是预期的行为。

请帮助我。以下是demo plunker的问题。

(function() {

  'use strict';

  angular
    .module('app', [])
    .controller('AppController', function($scope) {
      var vm = this;
      angular.extend(vm, {
        formdata: {
          username: "",
          vehicles: {
            bike: null,
            car: null,
            cycle: null
          }
        }
      });

      vm.isOptionsRequired = function(item) {
        // console.log("isOptionsRequired", item);
        var arr = Object.values(item);
        console.log("arr", arr);
        var final = arr.some(function(option) {
          return option > 0;
        });
        // console.log("final", final);
        return !final;
      };

      vm.updateForm = function() {
        console.log('updateForm called', vm.formdata);
      }

    }).directive('validateNumber', function($timeout) {
      return {
        restrict: 'A',
        require: 'ngModel',
        scope: {
          validateNumber: '='
        },
        link: function(scope, element, attr, ngModel) {
          function checkOut(text) {
            if (text < scope.validateNumber.min || text > scope.validateNumber.max) {
              console.info("if inside directive");
              ngModel.$setValidity('validRange', false);
            } else {
              console.info("else inside directive");
              ngModel.$setValidity('validRange', true);
              if (text) {
                var transformedInput = text.replace(/[^0-9]/g, '');
                if (transformedInput !== text) {
                  ngModel.$setValidity('validNumber', false);
                  angular.element(element).css({
                    'background-color': '#ffc7c7'
                  });
                  ngModel.$setViewValue(transformedInput);
                  ngModel.$render();
                } else {
                  $timeout(function() {
                    angular.element(element).css({
                      'background-color': '#ffffff',
                      'transition': 'background-color 40ms ease-out',
                      '-ms-transition': 'background-color 40ms linear',
                      '-webkit-transition': 'background-color 40ms linear'
                    });
                  }, 100);
                  ngModel.$setValidity('validNumber', true);
                }
                return transformedInput;
              }
              return undefined;
            }
          }
          ngModel.$parsers.unshift(checkOut);
        }
      };
    });
})();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://netdna.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.0/angular.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.16/angular-messages.min.js"></script>
<!DOCTYPE html>
<html ng-app="app">
<body class="container" ng-controller="AppController as vm">
  <h1>Hello Plunker!</h1>
  <form class="form-horizontal" name="wheelForm" novalidate="">
    <div class="row">
      <div class="form-group">
        <label class="col-md-4 control-label">Name</label>
        <div class="col-md-8" ng-class="{ 'has-error': wheelForm.username.$touched && wheelForm.username.$invalid }">
          <input type="text" name="username" class="form-control" ng-model="vm.formdata.username" required="" />
          <div ng-if="wheelForm.username.$touched && wheelForm.username.$invalid" ng-messages="wheelForm.username.$error" class="has-error">
            <span ng-message="required">Please enter name.</span>
          </div>
        </div>
      </div>
      <div class="form-group ">
        <label class="col-md-4"># of Bikes</label>{{wheelForm.vehicle_bike | json }}
        <div class="col-md-8" ng-class="{ 'has-error': wheelForm.vehicle_bike.$touched && wheelForm.vehicle_bike.$invalid }">
          <input type="text" placeholder="Enter 0 for no vehicles" name="vehicle_bike" class="form-control" ng-model="vm.formdata.vehicles.bike" ng-required="vm.isOptionsRequired(vm.formdata.vehicles)" validate-number="{min:0, max:10}" />
          <div ng-messages="wheelForm.vehicle_bike.$error" ng-if="wheelForm.vehicle_bike.$touched && wheelForm.vehicle_bike.$invalid" class="text-danger">
            <!-- <span ng-message="parse">Enter 0 if no bike servlet required</span> -->
            <span ng-message="validRange">Number must be between 0 and 10.</span>
            <span ng-message="required">Please enter Number.</span>
          </div>
        </div>
      </div>
      <div class="form-group ">
        <label class="col-md-4"># of Cars</label>{{wheelForm.vehicle_car | json }}
        <div class="col-md-8" ng-class="{ 'has-error': wheelForm.vehicle_car.$touched && wheelForm.vehicle_car.$invalid }">
          <input type="text" placeholder="Enter 0 for no vehicles" name="vehicle_car" class="form-control" ng-model="vm.formdata.vehicles.car" ng-required="vm.isOptionsRequired(vm.formdata.vehicles)" validate-number="{min:0, max:10}" />
          <div ng-messages="wheelForm.vehicle_car.$error" ng-if="wheelForm.vehicle_car.$touched && wheelForm.vehicle_car.$invalid" class="text-danger">
            <span ng-message="validRange">Number must be between 0 and 10.</span>
            <span ng-message="required">Please enter Number.</span>
          </div>
        </div>
      </div>
      <div class="form-group ">
        <label class="col-md-4"># of Cycles</label>{{wheelForm.vehicle_cycle | json }}
        <div class="col-md-8" ng-class="{ 'has-error': wheelForm.vehicle_cycle.$touched && wheelForm.vehicle_cycle.$invalid }">
          <input type="text" placeholder="Enter 0 for no vehicles" name="vehicle_cycle" class="form-control" ng-model="vm.formdata.vehicles.cycle" ng-required="vm.isOptionsRequired(vm.formdata.vehicles)" validate-number="{min:0, max:10}" />
          <div ng-messages="wheelForm.vehicle_cycle.$error" ng-if="wheelForm.vehicle_cycle.$touched && wheelForm.vehicle_cycle.$invalid" class="text-danger">
            <span ng-message="validRange">Number must be between 0 and 10.</span>
            <span ng-message="required">Please enter Number.</span>
          </div>
        </div>
      </div>
      <div class="form-actions m-t-lg text-center">
        <button ng-disabled="wheelForm.$invalid" class="btn btn-block btn-success" ng-click="vm.updateForm()">
          Update
        </button>
      </div>
    </div>
  </form>
</body>

</html>

2 个答案:

答案 0 :(得分:0)

我找到了解决方案,因为我错过了对ng-required的理解,如果输入框中有一些值(是否为0),那么满足ng-required就是为什么要解决问题。

通过在条件输入框上使用watch获得解决方案。下面是相关代码,(这里我使用json值作为$ watch,如果数组发生变化则不调用,所以改成json数据)

var

这是updated plunker

替代方法

它也可以在没有$scope.$watch(function() { console.log('inside watch'); return angular.toJson(vm.formdata.vehicles); }, function(nv, ov) { console.log(nv, ov); if (nv !== ov) { var arr = Object.values(angular.fromJson(nv)); // change json > array var arrVehicles = arr.map(Number); // change all array element from string to integer console.log("vehicle Array:", arrVehicles); var sum = arrVehicles.reduce(function(sum, cur) { // console.log(sum, cur); return sum + cur; }, 0); console.log("Boolean(sum)", Boolean(sum)); $timeout(function() { $scope.wheelForm.$setValidity("enough", Boolean(sum)); if( !Boolean(sum)) { vm.invalidRequest = true; vm.errorMessage = "At least 1 vehicle is required for the registration."; } else { vm.invalidRequest = false; vm.errorMessage = ""; } }, 0); } else { $scope.wheelForm.$setValidity("enough", false); } }); 的情况下实现,只需添加一个操作车辆总数的方法,然后将其作为表单提交按钮启用/禁用的标志重新添加。

JS

$watch

HTML

 vm.isEnoughVehicles = function(vehicles) {
     if (angular.isDefined(vehicles)) {
         var arrVehicles = Object.values(vehicles).map(Number); // change array value from string to integer
         var total = arrVehicles.reduce(function(sum, prev) {
             var cur = isNaN(prev) ? 0 : prev;
             return sum + cur;
         }, 0);
         return (total > 0 ? true : false);
     } else {
         return false;
     }
 };

update plunker

答案 1 :(得分:-1)

我对你的掠夺者做了一些改变,认为所有的问题都是固定的,因为我理解你的观点。这是链接 - https://plnkr.co/edit/bDzuBa?p=preview

choose [
    GET >=> pathScan "/instrument/%d" getResourceById 
    GET >=> pathScan "/instrument/%d/prices" getPricesById
]