【问题标题】:Proper use of ng-submit正确使用 ng-submit
【发布时间】:2016-01-31 00:41:36
【问题描述】:

我有一个向 Google 地理编码器提交位置并返回纬度/经度并更改地图的表单。如果我在图标上使用 ng-click,除非我点击两次,否则它不起作用。如果我在表单上使用 ng-submit,它会附加到 url 并且不执行任务。我觉得我快要让它发挥作用了,但我不知道自己做错了什么。

下面是表格

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

这里是函数

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

感谢@PSL,它已修复!见下文:

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

还有

$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();
    } 
  }); 
};

【问题讨论】:

    标签: javascript angularjs forms angularjs-ng-click ng-submit


    【解决方案1】:

    您需要在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();
        } 
      }); 
    

    每次单击时,ng-click 都会触发摘要循环,因此前一个循环会运行非角度异步调用并更新角度不知道的范围,当您再次单击它时,它会再次运行摘要循环并执行相同的操作,但那次您之前设置的值将被选中,这就是为什么需要点击 2 次。要让ng-submit 执行,您需要一个表单元素触发器,例如:buttoninput type="submit" 会导致表单上发生提交行为。除非您真的打算进行重定向,否则您还应该从表单中删除 action

    除此之外,您还可以在文本框上使用 ng-model 并将值传递给您的函数,而不是直接从 DOM 获取值。

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

    并通过ng-click 将值作为ng-click="convertLatLonToAddress(searchText)" 传递并在您的函数中使用它。

    为了避免您的控制器中出现scope.apply();,您可以将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;
          }
    
    });
    

    注入geoCoderService并使用以下方式获取数据:

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

    【讨论】:

    • @AlexMarple 如果你想让 ng-submit 工作,你可以使用 &lt;button&gt;&lt;/button&gt; 并相应地设置它的样式。如果您在文本框中输入回车键会发生什么,它也应该起作用?
    • 所以我在表单上有 ng-submit 并且我也有 ng-click 在包裹图标的锚点上。对锚点的点击效果很好。如果您按回车键(即使有一个视觉上隐藏的按钮),它会将 ?=whateverCityYouEntered 添加到 url。想法?顺便说一句,感谢您的帮助。
    • @AlexMarple 我不明白为什么需要填充表单操作?从表单中删除操作。
    • 这是一个很好的提示。我想我会加入它!
    【解决方案2】:

    试试这个

     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>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多