AngularJS google places 指令中的表单验证

AngularJS form validation inside google places directive

我有一个由以下指令创建的输入字段:

.directive('googlePlaces', function(){
        return {
            restrict:'E',
            replace:true,
            scope: {location:'='},
            template: function (elem, attrs) { 
                return '<div><div class="form-group" ng-class="{ \'has-error\' : '+attrs.form+'.google_places_ac.$invalid }"><label>Address*</label><input id="google_places_ac" required name="google_places_ac" type="text" class="form-control" placeholder="Address" /><p class="help-block" ng-message="required" ng-show="'+attrs.form+'.google_places_ac.$invalid">Message</p></div></div>'
            },
            link: function($scope, elm, attrs){
                var autocomplete = new google.maps.places.Autocomplete($("#google_places_ac")[0], {});
                google.maps.event.addListener(autocomplete, 'place_changed', function() {
                    var place = autocomplete.getPlace();
                    $scope.location = place.name + ',' + place.geometry.location.lat() + ',' + place.geometry.location.lng() + "," + place.formatted_address;
                    $scope.$apply();
                });
            }
        }
    })

我一直在竭尽全力为此字段添加必需的验证,但它不起作用。我对我的 HTML 表单中的其他输入字段执行相同操作并且工作正常。

这是相关的 HTML:

<form name="registrationForm" ng-submit="register()" novalidate>
...
<div class="col-xs-12">
            <google-places location=location form="registrationForm"></google-places>
</div>
...

我尝试了很多不同的方法,scope: {location:'=', form:'='}$compile,只是直接添加名称 registrationForm,或者只是 form。 None 有效。

如果有人能帮助我,我将不胜感激:)

您可以通过多种方式做到这一点。这里有几个。

1) 将消息的验证和显示、访问表单等与 googlePlaces 指令隔离开来,并将其控制权交给消费者,因为这确实是消费者关心的问题。他们可以完全控制如何显示、显示内容和显示位置。这将避免对仅负责提供位置选择的指令承担更多责任。让您的指令需要 ng-model 并指定必需的属性。

所以粗略的实现应该是这样的。

.directive('googlePlaces', function() {
  return {
    require:'ngModel',
    restrict: 'E',
    replace: true,
    scope: {
      location: '=ngModel'
    },
    template: function(elem, attrs) {
      return '<div><div class="form-group"><label>Address*</label><input id="google_places_ac" required name="google_places_ac" type="text" ng-model="locSearch" class="form-control" placeholder="Address" /></div><button type="button" ng-click="clear()">clear</button></div>'
    },
    link: function($scope, elm, attrs, ctrl) {
      var autocomplete = new google.maps.places.Autocomplete($("#google_places_ac")[0], {});
      google.maps.event.addListener(autocomplete, 'place_changed', function() {
        var place = autocomplete.getPlace();
        $scope.location = place.name + ',' + place.geometry.location.lat() + ',' + place.geometry.location.lng() + "," + place.formatted_address;
        $scope.$apply();
      });

      $scope.clear = function() {
        $scope.location = null;
      }
    }
  }
});

 <google-places name="location" ng-model=location required 
               ng-class="{ 'has-error' : registrationForm.location.$invalid }">
 </google-places>
 <span class="help-block" 
       ng-show="registrationForm.location.$invalid">Please specify location</span>

angular.module('app', []).directive('googlePlaces', function() {
  return {
    require:'ngModel',
    restrict: 'E',
    replace: true,
    scope: {
      location: '=ngModel'
    },
    template: function(elem, attrs) {
      return '<div><div class="form-group"><label>Address*</label><input id="google_places_ac" required name="google_places_ac" type="text" ng-model="location" class="form-control" placeholder="Address" /></div><button type="button" ng-click="clear()">clear</button></div>'
    },
    link: function($scope, elm, attrs, ctrl) {
      var autocomplete = new google.maps.places.Autocomplete($("#google_places_ac")[0], {});
      google.maps.event.addListener(autocomplete, 'place_changed', function() {
        var place = autocomplete.getPlace();
        $scope.location = place.name + ',' + place.geometry.location.lat() + ',' + place.geometry.location.lng() + "," + place.formatted_address;
        $scope.$apply();
      });

      $scope.clear = function() {
        $scope.location = null;
      }
    }
  }
});
.has-error input {
  border: 2px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?libraries=places"></script>
<div ng-app="app">
  <form name="registrationForm" ng-submit="register()" novalidate>
    <div class="col-xs-12">
    
      <google-places name="location" ng-model=location required ng-class="{ 'has-error' : registrationForm.location.$invalid }"></google-places>
      <span class="help-block" ng-show="registrationForm.location.$invalid">Please specify location</span>
    </div>
  </form>
</div>

2) 您可以通过两种方式将表单对象绑定到指令并从那里控制验证和显示消息。您需要在输入上放置一个 ng-model 才能正确启动验证。

.directive('googlePlaces', function() {
  return {
    restrict: 'E',
    replace: true,
    scope: {
      location: '=',
      form:'='
    },
    template: function(elem, attrs) {
      return '<div><div class="form-group" ng-class="{ \'has-error\' :form.google_places_ac.$invalid }"><label>Address*</label><input ng-model="selectedLocation" id="google_places_ac" required name="google_places_ac" type="text" class="form-control" placeholder="Address" /><p class="help-block" ng-message="required" ng-show="form.google_places_ac.$invalid">Message</p></div></div>'
    },
    link: function($scope, elm, attrs) {

      var autocomplete = new google.maps.places.Autocomplete($("#google_places_ac")[0], {});
      google.maps.event.addListener(autocomplete, 'place_changed', function() {

        var place = autocomplete.getPlace();
        $scope.location = place.name + ',' + place.geometry.location.lat() + ',' + place.geometry.location.lng() + "," + place.formatted_address;
        $scope.$apply();
      });
    }
  }
});

angular.module('app', []).directive('googlePlaces', function() {
  return {
    restrict: 'E',
    replace: true,
    scope: {
      location: '=',
      form: '='
    },
    template: function(elem, attrs) {
      return '<div><div class="form-group" ng-class="{ \'has-error\' :form.google_places_ac.$invalid }"><label>Address*</label><input ng-model="location" id="google_places_ac" required name="google_places_ac" type="text" class="form-control" placeholder="Address" /><p class="help-block" ng-message="required" ng-show="form.google_places_ac.$invalid">Message</p></div></div>'
    },
    link: function($scope, elm, attrs) {

      var autocomplete = new google.maps.places.Autocomplete($("#google_places_ac")[0], {});
      google.maps.event.addListener(autocomplete, 'place_changed', function() {

        var place = autocomplete.getPlace();
        $scope.location = place.name + ',' + place.geometry.location.lat() + ',' + place.geometry.location.lng() + "," + place.formatted_address;
        $scope.$apply();
      });
    }
  }
})
.has-error input {
  border: 2px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?libraries=places"></script>
<div ng-app="app">
  <form name="registrationForm" ng-submit="register()" novalidate>
    <div class="col-xs-12">
      <google-places location=location form="registrationForm"></google-places>
    </div>
  </form>
</div>