【问题标题】:set scope variable from outside controller in angular从外部控制器以角度设置范围变量
【发布时间】:2016-05-04 14:24:32
【问题描述】:

是否可以从控制器外部设置控制器的 $scope 变量?

例如,如果我有一个控制器:

app.controller('citySelectCtrl', ['$scope',function($scope){

}]);

还有一个全局范围内的函数,它有一个事件处理程序。现在我想在该事件发生时设置一个$scope 变量。可能吗?我的全局函数:

function initAutocomplete() {
    autocomplete = new google.maps.places.Autocomplete(
        /** @type {!HTMLInputElement} */(document.getElementById('autocomplete')),
        {
            componentRestrictions: {'country': 'in'},
            types: ['(cities)']
        });
    map = new google.maps.Map(document.getElementById('map'), {
        center: {lat: 22.5937, lng: 78.9629},
        zoom: 5,
        minZoom: 5
    });
}

autocomplete.addListener('place_changed', function() {
    infowindow.close();
    marker.setVisible(false);
    var place = autocomplete.getPlace();
    if (!place.geometry) {
      window.alert("Autocomplete's returned place contains no geometry");
      return;
    }

    // If the place has a geometry, then present it on a map.
    if (place.geometry.viewport) {
      map.fitBounds(place.geometry.viewport);
    } else {
      map.setCenter(place.geometry.location);
      map.setZoom(17);  // Why 17? Because it looks good.
    }
----------------------------------------------------------
    //SET $scope.city = place here
----------------------------------------------------------
    infowindow.setContent('<div><strong>' + place.name + '</strong><br>' + address);
    infowindow.open(map, marker);
  });

【问题讨论】:

  • 将此控制器范围作为参数传递给该函数
  • 你可以使用$scope的$rootscope变量来设置全局值
  • 就像@ramsingh 提到的$rootScope 是一个全局变量,可以在模块中的所有控制器中使用,而$scope 是特定于当前控制器的。
  • $rootscope 是...的财产?应用程序?
  • @dreamweiver 如何在 Angular 应用范围之外访问 $rootScope?

标签: javascript angularjs


【解决方案1】:

我们可以使用$injector 来访问作用域外的 Angular 服务。 以你为例。

// If the place has a geometry, then present it on a map.
if (place.geometry.viewport) {
  map.fitBounds(place.geometry.viewport);
} else {
  map.setCenter(place.geometry.location);
  map.setZoom(17);  // Why 17? Because it looks good.
}
----------------------------------------------------------
    var elem = angular.element(document.querySelector('[ng-app]'));
    var injector = elem.injector();
     var $rootScope = injector.get('$rootScope');   
     $rootScope.$apply(function(){
       $rootScope.city = place //or city;
     });
----------------------------------------------------------
infowindow.setContent('<div><strong>' + place.name + '</strong><br>' + address);
infowindow.open(map, marker);
});

您可以在控制器中使用。

app.controller('citySelectCtrl', ['$scope','$rootScope',
    function ($scope,$rootScope) {         
         $rootScope.city = {};

    }
]);

DEMO

更多详情请查看this

希望对你有帮助

【讨论】:

    【解决方案2】:

    您可以尝试使用 $rootscope 中的 $broadcast 来通知您的控制器事件已发生。

    //rootscope
    $rootscope.$broadcast("myevent",eventObjectToBePassed);
    
    //your controller
    $scope.$on("myevent",function(eventObject){
    
    //do something
    
    });
    

    更简洁的方法是将 rootscope 注入服务并创建一个 sendEvent 函数来实际执行 $rootscope.$broadcast。

    【讨论】:

      【解决方案3】:

      在使用 Angular 应用程序时,您不应直接使用全局范围变量。推荐的方式是将此功能包装在指令中并在模板中使用该指令。这样您就可以访问$scope来更新值。例如:

      angular.directive('mapAutoComplete', function () {
        return {
          restrict: 'E',
          link: function (scope, elem, attr) {
            // Add your map and autocomplete here
      
            // Now you can use the `scope` to update the $scope of the parent controller
          }
        }
      });
      

      在您的 html 中,使用如下指令:

      <map-auto-complete></map-auto-complete>
      

      这将使包含视图的控​​制器的范围在指令中可用作scope

      请参阅这些以了解使用 directives 而非直接 dom 操作和可重用功能的最佳实践 http://ng-learn.org/2014/01/Dom-Manipulations/ https://stackoverflow.com/a/15012542/3878940

      【讨论】:

      • 我需要给 Google 地图 API 一个回调,以便在脚本加载时调用。我应该如何给它一个非全局函数?
      • 您可以使用指令定义中的scope 属性将值传递到指令中。参考:docs.angularjs.org/guide/directivestackoverflow.com/a/18378602/3878940 回答 SO
      • 这是回调的地方:script(src="https://maps.googleapis.com/maps/api/js?key=MY_API_KEY&amp;callback=**initAutocomplete**&amp;libraries=places", async, defer)我应该用什么替换它?
      【解决方案4】:

      我可以考虑两种方法来做到这一点

      1. 使用$rootScope 这是最简单的方法。但如果它不是真正的全局变量,我个人不太喜欢它。

      2. 编写事件处理程序并在控制器中监听

      【讨论】:

        【解决方案5】:

        use 可以像这样使用 $rootScope。

        app.controller('citySelectCtrl', ['$scope', '$rootScope', function($scope, $rootScope){
            //$rootScope.city = place here;
        }]);
        

        并且使用可以访问全局函数中的变量

        function initAutocomplete() {
            //$rootScope.city = place here;
        }
        

        【讨论】:

        • 全局函数在脚本加载时被调用。除非脚本已加载,否则我无法调用它。
        • 使用可以使用$rootScope
        • $rootScope 不是已声明的变量。它不可用,就像您在这里使用它一样。
        • 是的,我知道它没有声明为变量。它可以在状态级别设置并在控制器中使用。
        【解决方案6】:

        您可以使用var requiredElemScope = angular.element(ELEMENT_SELECTOR).scope(); 来获取元素的范围。然后你可以给作用域变量赋值为requiredElemScope.city = someValue;

        这里ELEMENT_SELECTOR 是控制器所附加的dom 选择器。

        【讨论】:

          猜你喜欢
          • 2016-12-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-05-02
          • 1970-01-01
          相关资源
          最近更新 更多