从服务AngularJs中修改$ scope

Fac*_*ari 1 javascript google-maps angularjs

我正在开发一个基于Gmaps Api的地理定位应用程序.问题是,为了通过用户事件添加新标记,我已经提供了一个服务,只需向地图事件添加一个监听器,并在单击时添加标记.问题是我找不到从服务中修改某些$ scope属性的方法.这是我写的服务:

climbingApp.factory('Markers', function(){
    return {
        addListener: function() {
            google.maps.event.addListener(
                map,
                'click',
                 function( e ) {
                    var marker = new google.maps.Marker({
                        position: e.latLng,
                        map: map
                    });

                }
            );
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

如何返回de e.latLng值并使用该值设置一些$ scope.property?

Mic*_*ord 11

正如@Ajaybeniwal所说,你不应该触摸控制器外的范围.您可以更改addListener以便接受回调:

climbingApp.factory('Markers', function($rootScope) {
    return {
        addListener: function(callback) {
            google.maps.event.addListener(map, 'click', function(e) {
                $rootScope.$apply(function() { callback(e); });
            });
         }
    }
});
Run Code Online (Sandbox Code Playgroud)

现在您可以在控制器中使用它:

Markers.addListener(function(e) {
    $scope.model.position = e.latLng;
});
Run Code Online (Sandbox Code Playgroud)

您也可以使用promise而不是回调:

climbingApp.factory('Markers', function($rootScope, $q) {
    return {
        addListener: function() {
            var deferred = $q.defer();
            google.maps.event.addListener(map, 'click', function(e) {
                $rootScope.$apply(function() { deferred.resolve(e); });
            });
            return deferred.promise;
         }
    }
});
Run Code Online (Sandbox Code Playgroud)

然后你的控制器看起来像这样:

Markers.addListener().then(function(e) {
    $scope.model.position = e.latLng;
});
Run Code Online (Sandbox Code Playgroud)

Promise比回调更有优势:您可以将它们直接绑定到视图,Angular会在可用时立即呈现正确的值.查看此帖子了解有关此事的更多信息.

最后但并非最不重要的是,请注意您需要$rootScope.$apply()在两种情况下调用,以便Angular触发摘要周期并正确处理所有内容.这是必需的,因为Angular一无所知,google.maps.event.addListener并且在执行gmaps回调时不会得到通知.