简体   繁体   English

正确使用ng-submit

[英]Proper use of ng-submit

I have a form that submits a location to Google's Geocoder and returns the lat/long and changes the map. 我有一个向Google的Geocoder提交位置并返回经纬度并更改地图的表格。 If I use ng-click on the icon it doesn't work unless I click on it twice. 如果我使用ng键单击图标,除非我单击两次,否则它不起作用。 If I use ng-submit on the form it appends to the url and doesn't perform the task. 如果我在表单上使用ng-submit,它将附加到url上并且不执行任务。 I feel like I'm close to getting this to work but I'm lost as to what I'm doing wrong. 我觉得我快要解决这个问题了,但是我对自己做错的事情迷失了。

Below is the form 下面是表格

<li>
  <form action="" class="search-form" ng-submit="convertLatLonToAddress()">
      <div class="form-group has-feedback">
      <label for="search" class="sr-only">Search</label>
      <input type="text" class="form-control" name="search" id="search" placeholder="Search for an address or place name">
          <i class="fa fa-search form-control-indicator"></i>                        
    </div>
  </form>
</li> 

And here is the function 这是功能

$scope.convertLatLonToAddress = function(){
  var address = $('#search').val();
  var geocoder = new google.maps.Geocoder();

  geocoder.geocode( { 'address': address}, function(results, status) {
    if (status == google.maps.GeocoderStatus.OK) {
      var latitude = results[0].geometry.location.lat();
      var longitude = results[0].geometry.location.lng();
      // console.log(latitude + ' and ' + longitude);
      $scope.center.lat = latitude;
      $scope.center.lon = longitude;
    } 
  }); 
};

Thanks to @PSL it's fixed! 感谢@PSL,它是固定的! See below: 见下文:

<li>
  <form class="search-form" ng-submit="convertLatLonToAddress(searchText)">
    <div class="form-group has-feedback">
      <label for="search" class="sr-only">Search</label>
      <input type="text" class="form-control" name="search" id="search" placeholder="Search for an address or place name" ng-model="searchText">
      <button style="visibility: hidden"></button>
        <a ng-click="convertLatLonToAddress(searchText)">
          <i class="fa fa-search form-control-indicator"></i>                        
        </a>
    </div>
  </form>
</li> 

And

$scope.convertLatLonToAddress = function(searchText){
  // var address = $('#search').val();
  var address = searchText;
  var geocoder = new google.maps.Geocoder();

  geocoder.geocode( { 'address': address}, function(results, status) {
    if (status == google.maps.GeocoderStatus.OK) {
      var latitude = results[0].geometry.location.lat();
      var longitude = results[0].geometry.location.lng();
      // console.log(latitude + ' and ' + longitude);
      $scope.center.lat = latitude;
      $scope.center.lon = longitude;
      $scope.$apply();
    } 
  }); 
};

You need to invoke the digest cycle manually inside the async call of geocode , since geocode does not run inside angular context. 您需要在geocode的异步调用中手动调用摘要循环,因为geocode不在角上下文中运行。

geocoder.geocode( { 'address': address}, function(results, status) {
    if (status == google.maps.GeocoderStatus.OK) {
      var latitude = results[0].geometry.location.lat();
      var longitude = results[0].geometry.location.lng();
      // console.log(latitude + ' and ' + longitude);
      $scope.center.lat = latitude;
      $scope.center.lon = longitude;
      $scope.$apply();
    } 
  }); 

Everytime you click, ng-click triggers the digest cycle so previous cycle runs the non angular async call and updated scope which angular is unaware, when you click on it again it runs the digest cycle again and does the same but that time the values you set previously will be picked and that is why it takes 2 clicks. 每次单击时, ng-click触发摘要循环,因此上一个循环会运行非角度异步调用并更新角度不知道的范围,当再次单击它时,它将再次运行摘要循环并执行相同的操作,但此时的值是之前设置的设置将被选中,这就是为什么需要2次点击。 For ng-submit to execute you need a form element trigger, ex: a button or input type="submit" that causes submit behavior to happen on the form. 要执行ng-submit ,您需要一个表单元素触发器,例如:一个buttoninput type="submit" ,它会导致表单上发生提交行为。 You should also remove action from form unless you really intend to do a redirection. 除非您确实打算进行重定向,否则还应该从表单中删除action

Apart from that you can use ng-model on the textbox and pass the value to your function as well instead of getting value from DOM directly. 除此之外,您可以在文本框中使用ng-model并将值也传递给函数,而不是直接从DOM获取值。

<input type="text" class="form-control" name="search" id="search" placeholder="Search for an address or place name" ng-model="searchText">

and pass the value via ng-click as ng-click="convertLatLonToAddress(searchText)" and use it inside your function. 并以ng-click="convertLatLonToAddress(searchText)"通过ng-click传递值,并在函数中使用它。

In order to avoid scope.apply(); 为了避免scope.apply(); in your controller you could abstract out geoCoder to an angular service and return a promise (creating deferred object) and use that service in your controller. 在您的控制器中,您可以将geoCoder抽象为一个有角度的服务,并返回一个promise(创建延迟的对象),然后在控制器中使用该服务。

myApp.service('geoCoderService', ['$q', function($q){
      this.getCoordinates = function(address){
          var defer = $q.defer();
           var geocoder = new google.maps.Geocoder();

          geocoder.geocode( { 'address': address}, function(results, status) {
           if (status == google.maps.GeocoderStatus.OK) {
             var latitude = results[0].geometry.location.lat();
             var longitude = results[0].geometry.location.lng();
             return defer.resolve({latitude :latitude , longitude :longitude });
           } 
          //faliure
          defer.reject(status);
       }); 
          return defer.promise;
      }

});

inject geoCoderService and get data using: 注入geoCoderService并使用以下方法获取数据:

 geoCoderService.getCoordinates(address).then(function(coordinates){
     //populate it
 }).catch(function(errorStatus){  /*ooops Error*/ })

Try this 尝试这个

  var app = angular.module('myApp', []); app.controller('myCtrl', function($scope) { $scope.convertLatLonToAddress = function() { var address = $('#search').val(); var geocoder = new google.maps.Geocoder(); geocoder.geocode({ 'address': address }, function(results, status) { if (status == google.maps.GeocoderStatus.OK) { $scope.lat = results[0].geometry.location.lat(); $scope.lon = results[0].geometry.location.lng(); console.log($scope.lat + ' and ' + $scope.lon); setTimeout(function(){$scope.$apply();},0) } }); }; }); 
 <script src="https://maps.googleapis.com/maps/api/js?v=3.exp"></script> <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <body> <div ng-app="myApp" ng-controller="myCtrl"> <li> <div class="form-group has-feedback"> <label for="search" class="sr-only">Search</label> <input type="text" class="form-control" name="search" id="search" placeholder="Search for an address or place name"> <i class="fa fa-search form-control-indicator"></i> <button ng-click="convertLatLonToAddress()">Click</button> <br> Lat : <input type="text" ng-model="lat"><br> Lon : <input type="text" ng-model="lon"> </div> </li> </div> </body> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM