2016-03-09 48 views
0

我想根据用户的位置创建一个基本的天气应用,我使用的是JavaScript地理定位服务。一切有关的位置和天气如预期般运作。
我的问题是当用户拒绝位置请求时,我想要做的就是隐藏天气数据(我无法获取)并显示相应的消息。
HTML:

<body ng-app="weatherApp"> 
    <div class="container text-center" style="margin-top: 15vh" ng-controller="weatherCtrl"> 
    <h1>Local Weather App</h1> 
    <h3>{{error}}</h3> 
    <div class="row" ng-hide="showError"> 
     <div id="loc-col" class="col-xs-3 col-xs-offset-1"> 
     <h3>{{data.name}}</br> 
     <small>{{data.sys.country}}</small></h3> 
     </div> 
     <div id="temp-col" class="col-xs-4"> 
     <h3>{{data.main.temp}} {{degree}}&deg;</h3> 
     </div> 
     <div id="weather-col" class="col-xs-3"> 
     <h3>{{data.weather[0].main}} </br><small>{{data.weather[0].description}}</small> </h3> 
     </div> 
     <div id="icon-col" class="col-xs-6 col-xs-offset-3"> 
     <img id="icon" class="img-responsive" ng-src="{{icon}}"> 
     </div> 
    </div> 
    </div> 
</body> 

该错误消息应在<h3>的H1的下方。

JS:

'use strict'; 
var app = angular.module('weatherApp', []); 

app.factory('weatherFactory', ['$http', function($http){ 
    var weather = {}; 

    weather.getWeather = function(lat, lon){ 
    return $http.jsonp("http://api.openweathermap.org/data/2.5/weather?lat="+lat+"&lon="+lon+"&units=metric&callback=JSON_CALLBACK"); 
    }; 
    return weather; 
}]); 

app.controller('weatherCtrl', ['$scope', 'weatherFactory', '$http', function($scope, weatherFactory, $http){ 
    $scope.degree = "C"; 

    $scope.error = ""; 
    $scope.showError = false; 

    var icons = { }; 

    function getWeatherFromPos(position){ 
    var lat = position.coords.latitude; 
    var lon = position.coords.longitude; 
    weatherFactory.getWeather(lat,lon).success(
      function(data){ 
       $scope.data = data; 
       $scope.icon = icons[data.weather[0].icon]; 
      } 
     ).error(function(error){ 
      setError(error); 
      }); 
    } 

    function setError(error){ 
    $scope.showError = true; 
    $scope.error = error; 
    } 

    //THIS IS THE RELEVANT CODE: 
    if (navigator.geolocation) { 
     navigator.geolocation.getCurrentPosition(
     function(position) { 
      getWeatherFromPos(position); 
     }, 
     function() { 
      //EXECUTED UPON REJECTION 
      setError("Geolocation service failed."); 
     } 
    ); 
    } 
    else { 
     setError("Your browser doesn't support geolocation."); 
    } 
}]); 

当我打开了安慰时,安慰我执行以下命令:

angular.element($(".row")).scope().error 
"Geolocation service failed." 

所以不知何故变量都得到更新,但没有显示错误消息,天气数据不会隐藏。

+0

'angular.element($( “行”))'是元素的集合除非那个班只有一个。 – charlietfl

+0

@charlietfl正如您在html代码中看到的那样,该类中只有一个元素 –

回答

1

您的setError函数执行的时间为$digest循环的角度。 你可以做如下:

function setError(error){ 
    $scope.showError = true; 
    $scope.error = error; 
    $scope.$apply(); 
    } 

function setError(error){ 
    $scope.$apply(function() { 
     $scope.showError = true; 
     $scope.error = error; 
    } 
} 

P.S:这是关心setError("Geolocation service failed.");setError("Your browser doesn't support geolocation.");

setError(error)这是不正常使用$apply,因为它已经内$digest循环(也没有必要调用$apply方法)。请记住,只有在角度摘要循环外进行了一些更改后,才需要致电$apply。查看更多有关它https://docs.angularjs.org/api/ng/type/ $ rootScope.Scope#$适用

+0

谢谢,有任何机会可以解释为什么表达式在$ digest循环之外,我该如何识别和防止这种情况? –

+1

将所有函数实现为'$ scope'方法,并且所有代码都将在'$ digest loop'内部执行。例如:'$ scope.setError = ...'你可以将它称为'$ scope.setError(...)' –

+0

添加$ scope不起作用,使用$ apply就像你在答案有帮助,但非常感谢。 –

0

我想感谢你错过了NG-绑定:

<h3 ng-bind="error">{{error}}</h3> 
+0

'ng-bind =“error”''和'{{error}}'做同样的事情 – charlietfl

+0

我在自己的项目中看到它会产生影响 – alexey

+0

区别在哪?将它们一起使用是多余的。阅读文档...他们说我也是这么说的:https://docs.angularjs.org/api/ng/directive/ngBind – charlietfl