【问题标题】:AngularJS : service - controller - view data bindingAngularJS:服务-控制器-视图数据绑定
【发布时间】:2015-01-21 18:43:49
【问题描述】:

我正在尝试在服务、控制器和视图之间绑定数据。下面,我提供了该应用的 plunker 链接。

基本上,“dataService”具有查找地理位置的功能。该函数设置变量dataService.locationDone。

dataService 被分配给 'HomeController' 中的 $scope.data。

在 home.html 中,我引用 data.locationDone 的值来显示不同的标签。

问题是,在dataService中修改locationDone变量后,home.html中的标签并没有改变。

插件链接:http://embed.plnkr.co/BomSztgC7PzGMzJyDKoF/preview

服务:

storelocator.factory('dataService', [function() {
    var data = {
        locationDone: 0,
        position: null,
        option: null
    }

    var getLocation = function() {
        data.locationDone = 0;

        if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition(function (pos) {
                data.locationDone = 1;
                data.position = pos;
                console.log('got location ', data.locationDone);
            }, function () {
                data.locationDone = 2;
            });
        } else {
            data.locationDone = 3;
        }
    };

    getLocation();

    return data;
}]);

控制器:

storelocator.controller('HomeController', ['$scope', '$location', 'dataService', function ($scope, $location, dataService) {
        $scope.data = dataService;
        console.log('Home ctrl', $scope.data.locationDone);

        $scope.fn = {};
        $scope.fn.showOne = function () {
            $scope.data.option = 3;
            $location.path('/map');
        };

        $scope.fn.showAll = function () {
            $scope.data.option = 99;
            $location.path('/map');
        };
}]);

查看:

<div layout="column" layout-align="start center">
    <div layout="column" layout-margin layout-padding>
        <div flex layout layout-margin layout-padding>
            <md-whiteframe flex class="md-whiteframe-z1" layout layout-align="center center" ng-show="data.locationDone==0">
                <span flex>Awaiting location information.</span>
            </md-whiteframe>
            <md-whiteframe flex class="md-whiteframe-z1" layout layout-align="center center" ng-show="data.locationDone==2"><span flex>Error in getting location.</span>
            </md-whiteframe>
            <md-whiteframe flex class="md-whiteframe-z1" layout layout-align="center center" ng-show="data.locationDone==3"><span flex>The browser does not support location.</span>
            </md-whiteframe>
        </div>
        <md-button flex ng-show="data.locationDone==1" class="md-accent md-default-theme md-raised" ng-click="fn.showOne()">Find Nearest Three Stores</md-button>
        <div flex></div>
        <md-button ng-show="data.locationDone==1" flex class="md-accent md-default-theme md-raised" ng-click="fn.showAll()">Find All Stores</md-button>

    </div>
</div>

【问题讨论】:

    标签: angularjs angularjs-scope angularjs-service angularjs-controller


    【解决方案1】:

    您正在更新服务范围内定义的变量locationDone。它不会对您在服务期间返回的对象产生任何影响(稍后更新时)。而是在您的服务中预定义一个对象并更新引用而不是变量的属性。 另请注意,由于您使用的是本机异步 api,它会超出角度上下文,您需要手动调用摘要循环,方法是在您的情况下执行 $rootScope.$apply(),或者仅使用 $timeout 将您的更新包装在 $timeout 中。然而更好的方法是在 dataService 中创建一个 api,方法返回 $q promise。

    超时

    .factory('dataService', ['$timeout', function($timeout) {
    
        var service = { //Define here;
            locationDone: 0,
            position: null,
            option: null
        }
    
        var getLocation = function() {
            service.locationDone = 0;
    
            if (navigator.geolocation) {
                navigator.geolocation.getCurrentPosition(function (pos) {
                  $timeout(function(){
                    service.locationDone = 1;
                    service.position = pos;
                  });
                }, function () {
                  $timeout(function(){
                    service.locationDone = 2;
                  });
                });
            } else {
                service.locationDone = 3;
            }
        };
    
        getLocation();
    
        return service; //return it
     }]);
    

    使用 qpromise 实现:

    .factory('dataService', ['$q', function($q) {
    
    
        return {
          getLocation:getLocation
        };
    
       function getLocation() {
    
            if (navigator.geolocation) {
              var defer = $q.defer();
                navigator.geolocation.getCurrentPosition(function (pos) {
                    defer.resolve({locationDone : 1,position : pos})
                }, function () {
                   defer.resolve({ locationDone : 2});
                });
              return defer.promise;
            }
    
            return $q.when({locationDone : 3});
    
        };
    
    
     }]);
    

    在你的控制器中:

        $scope.data = {};
        dataService.getLocation().then(function(result){
          $scope.data = result;
        });
    

    演示

    angular.module('app', []).controller('HomeController', ['$scope', '$location', 'dataService', function ($scope, $location, dataService) {
            $scope.data = {};
            dataService.getLocation().then(function(result){
              $scope.data = result;
            })
            
            console.log('Home ctrl', $scope.data.locationDone);
    
            $scope.fn = {};
            $scope.fn.showOne = function () {
                $scope.data.option = 3;
                $location.path('/map');
            };
    
            $scope.fn.showAll = function () {
                $scope.data.option = 99;
                $location.path('/map');
            };
    }]).factory('dataService', ['$q', function($q) {
       
        
        return {
          getLocation:getLocation
        };
    
       function getLocation() {
              
            if (navigator.geolocation) {
              var defer = $q.defer();
                navigator.geolocation.getCurrentPosition(function (pos) {
                    defer.resolve({locationDone : 1,position : pos})
                }, function () {
                   defer.resolve({ locationDone : 2});
                });
              return defer.promise;
            }
                
            return $q.when({locationDone : 3});
            
        };
    
       
     }]);
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
    <div ng-app="app" ng-controller="HomeController">
      <div layout="column" layout-align="start center">
        <div layout="column" layout-margin layout-padding>
            <div flex layout layout-margin layout-padding>
                <md-whiteframe flex class="md-whiteframe-z1" layout layout-align="center center" ng-show="data.locationDone==0">
                    <span flex>Awaiting location information.</span>
                </md-whiteframe>
                <md-whiteframe flex class="md-whiteframe-z1" layout layout-align="center center" ng-show="data.locationDone==2"><span flex>Error in getting location.</span>
                </md-whiteframe>
                <md-whiteframe flex class="md-whiteframe-z1" layout layout-align="center center" ng-show="data.locationDone==3"><span flex>The browser does not support location.</span>
                </md-whiteframe>
            </div>
            <md-button flex ng-show="data.locationDone==1" class="md-accent md-default-theme md-raised" ng-click="fn.showOne()">Find Nearest Three Stores</md-button>
            <div flex></div>
            <md-button ng-show="data.locationDone==1" flex class="md-accent md-default-theme md-raised" ng-click="fn.showAll()">Find All Stores</md-button>
    
        </div>
    </div>
    </div>

    【讨论】:

    • 我做了这些更改,但仍然无法正常工作。我帖子中的 plunker 链接已更新。
    • 我无法真正访问 plunker。
    • @Srik navigator.geolocation.getCurrentPosition 是异步正确且无角度的吗?你可以注入 $timeout 并将 data.locationDone = 1; data.position = pos; 包裹在 $timeout 中
    • 是的。它是异步的,随浏览器一起提供。 w3schools.com/HTML/html5_geolocation.asp
    • @Srik 这是一个非角度的东西。所以你需要理想地实现一个承诺模式或在超时中换行。很快更新我的答案
    猜你喜欢
    • 2018-09-29
    • 1970-01-01
    • 1970-01-01
    • 2014-09-05
    • 1970-01-01
    • 2016-09-02
    • 1970-01-01
    • 2014-01-24
    • 1970-01-01
    相关资源
    最近更新 更多