AngularJS form validation inside google places directive

爱⌒轻易说出口 提交于 2019-12-11 14:16:45

问题


I have an input field that is create by the following 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();
                });
            }
        }
    })

I have been trying exhaustively to add required validation to this field, but it doesn't work. I do the same for other input fields in my HTML form and it works fine.

This is the relevant HTML:

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

I've tried many different things, scope: {location:'=', form:'='}, $compile, just adding directly the name registrationForm, or simply form. None of it worked.

I would really appreciate if someone could help me with this :)


回答1:


You could do this in many ways. Here are couple of them.

1) Isolate the validation and display of messages, accessing form etc from the googlePlaces directive and have the control of it given to the consumer as it really is a consumer's concern. They can have full control over how to display, what to display and where to display. This would avoid any more responsibilities to the directive who will just be responsible for providing the place selection. Have your directive require the ng-model and specify required attribute as well.

So a rough implementation would be something like this.

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

and

 <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) You can 2 way bind the form object to the directive and control the validation and display message from there. You would need to place an ng-model on the input in order for validation to kick in properly.

.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>


来源:https://stackoverflow.com/questions/33353765/angularjs-form-validation-inside-google-places-directive

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!