如何在一个控制器中从另一个控制器获取值?

时间:2015-07-26 14:07:17

标签: javascript angularjs

有角度的应用。使用ui-select。

<div class="col-md-12" ng-controller="FlatController as flat">
   <form ng-submit="flat.createFlat()">
      <ui-select ng-model="flat.flatData.typelocal" theme="bootstrap">
          <ui-select-match placeholder="Type" id="localtype">
              {{ $select.selected.type }}
          </ui-select-match>
          <ui-select-choices repeat="uitypelocal.type as uitypelocal in flat.typelocal1 track by $index | filter: $select.search">
             <div ng-bind-html="uitypelocal.type | highlight: $select.search"></div>
          </ui-select-choices>
      </ui-select>
       <button class="btn btn-danger">Send</button>
  </form>
</div>

在表格中我有一些输入和选择。现在,我希望从另一个控制器中选择数据。我该怎么办?

我有服务:

angular.module('flatService', [])
    .factory('Flat', function($http){
        var flatFactory = {};

        flatFactory.allFlats = function(){
            return $http.get('/api/flats');
        };

        flatFactory.create = function(flatData){
            return $http.post('/api/addflat', flatData);
        };

        return flatFactory;

    })
});

3 个答案:

答案 0 :(得分:6)

如果您想将一个控制器调用另一个控制器,则可以使用五种方法

  1. $ rootScope。$ emit()和$ rootScope。$ broadcast()
  2. 如果第二个控制器是孩子,则可以使用父子通信。
  3. 使用服务
  4. 有点黑客 - 在angular.element()
  5. 的帮助下
  6. 注入'$ controller'
  7.   

    <强> 1。 $ rootScope。$ emit()和$ rootScope。$ broadcast()

    控制器及其范围可能会被破坏, 但$ rootScope仍然在整个应用程序中,这就是我们采用$ rootScope的原因,因为$ rootScope是所有范围的父级。

    如果您正在进行从父母到孩子的沟通,即使孩子想与其兄弟姐妹沟通,您也可以使用$ broadcast

    如果您正在从孩子到父母进行沟通,那么没有兄弟姐妹进行过调用,那么您可以使用$ rootScope。$ emit

    HTML

    <body ng-app="myApp">
        <div ng-controller="ParentCtrl" class="ng-scope">
          // ParentCtrl
          <div ng-controller="Sibling1" class="ng-scope">
            // Sibling first controller
          </div>
          <div ng-controller="Sibling2" class="ng-scope">
            // Sibling Second controller
            <div ng-controller="Child" class="ng-scope">
              // Child controller
            </div>
          </div>
        </div>
    </body>
    

    Angularjs代码

     var app =  angular.module('myApp',[]);//We will use it throughout the example 
        app.controller('Child', function($rootScope) {
          $rootScope.$emit('childEmit', 'Child calling parent');
          $rootScope.$broadcast('siblingAndParent');
        });
    
    app.controller('Sibling1', function($rootScope) {
      $rootScope.$on('childEmit', function(event, data) {
        console.log(data + ' Inside Sibling one');
      });
      $rootScope.$on('siblingAndParent', function(event, data) {
        console.log('broadcast from child in parent');
      });
    });
    
    app.controller('Sibling2', function($rootScope) {
      $rootScope.$on('childEmit', function(event, data) {
        console.log(data + ' Inside Sibling two');
      });
      $rootScope.$on('siblingAndParent', function(event, data) {
        console.log('broadcast from child in parent');
      });
    });
    
    app.controller('ParentCtrl', function($rootScope) {
      $rootScope.$on('childEmit', function(event, data) {
        console.log(data + ' Inside parent controller');
      });
      $rootScope.$on('siblingAndParent', function(event, data) {
        console.log('broadcast from child in parent');
      });
    });
    

    在$ emit'childEmit'的上面代码控制台中不会调用子兄弟姐妹内部,它将仅调用父内部,其中$ broadcast也会在兄弟姐妹和父母内部调用。这是性能进入行动的地方。 $ emit是首选的,如果您使用子到父通信,因为它会跳过一些脏检查。

      

    <强> 2。如果第二个控制器是孩子,您可以使用子父母沟通

    它是最好的方法之一,如果你想做孩子父母沟通,孩子想要与直接父母沟通那么它就不需要任何种类的广播或$ emit但是如果你想从父母到孩子进行沟通,那么你必须使用服务或$ broadcast

    例如HTML: -

    <div ng-controller="ParentCtrl">
     <div ng-controller="ChildCtrl">
     </div>
    </div>
    

    Angularjs

     app.controller('ParentCtrl', function($scope) {
       $scope.value='Its parent';
          });
      app.controller('ChildCtrl', function($scope) {
       console.log($scope.value);
      });
    

    每当你使用child to parent通信时,Angularjs将搜索子内部的变量,如果内部不存在,那么它将选择查看父控制器内的值。

      

    3.使用服务

    AngularJS使用服务架构支持“分离关注点”的概念。服务是javascript函数,仅负责执行特定任务。这使得它们成为个体实体可维护且可测试。服务使用Angularjs的依赖注入mecahnism注入服务

    Angularjs代码:

    app.service('communicate',function(){
      this.communicateValue='Hello';
    });
    
    app.controller('ParentCtrl',function(communicate){//Dependency Injection
      console.log(communicate.communicateValue+" Parent World");
    });
    
    app.controller('ChildCtrl',function(communicate){//Dependency Injection
      console.log(communicate.communicateValue+" Child World");
    });
    

    它将输出Hello Child World和Hello Parent World。根据Angular docs of services Singletons - 依赖于服务的每个组件都获得对服务工厂生成的单个实例的引用

      

    4.黑客攻击 - 在angular.element()的帮助下

    此方法通过其Id /唯一class从元素获取scope()。angular.element()方法返回元素,scope()使用另一个变量的$ scope变量使用另一个变量的$ scope变量而不是良好的做法。

    HTML: -

    <div id='parent' ng-controller='ParentCtrl'>{{varParent}}
     <span ng-click='getValueFromChild()'>Click to get ValueFormChild</span>
     <div id='child' ng-controller='childCtrl'>{{varChild}}
       <span ng-click='getValueFromParent()'>Click to get ValueFormParent </span>
     </div>
    </div>
    

    Angularjs: -

    app.controller('ParentCtrl',function($scope){
     $scope.varParent="Hello Parent";
      $scope.getValueFromChild=function(){
      var childScope=angular.element('#child').scope();
      console.log(childScope.varChild);
      }
    });
    
    app.controller('CarentCtrl',function($scope){
     $scope.varChild="Hello Child";
      $scope.getValueFromParent=function(){
      var parentScope=angular.element('#parent').scope();
      console.log(parentScope.varParent);
      }
    }); 
    

    在上面的代码控制器在Html上显示它们自己的值,当你点击文本时,你将相应地在控制台中获得值。如果你点击父控制器span,浏览器将控制child的值,反之亦然。

      

    5.注意'$ controller'

    您可以在父控制器(MessageCtrl)中注入'$ controller'服务,然后使用以下方法实例化/注入子控制器(DateCtrl): $scope.childController = $controller('childController', { $scope: $scope.$new() });

    现在,您可以通过调用其方法来访问子控制器中的数据,因为它是一项服务 如果有任何问题,请告诉我。

答案 1 :(得分:2)

视图的范围由其控制器决定。但是,angular允许嵌套视图范围继承,这意味着嵌套在另一个视图中的视图可以访问父视图的范围..例如:

<div ng-controller="OuterCtrl">
   <div ng-controller="InnerCtrl">
      ...
   </div>
<div>

内部div可以访问InnerCtrl的范围以及OuterCtrl的范围,但外部div只能访问OuterCtrl的范围。

如果您需要在非相关控制器(那些与嵌套视图无关的控制器)之间共享数据,那么数据应该由可以注入控制器的服务提供,如:

app.factory('service', function() {
   ...
   return {
     data: someData
   };
});

app.controller('ctrl1', [... function(..., service) {
    $scope.data = service.data;
}]);

app.controller('ctrl2', [... function(..., service) {
    $scope.data = service.data;
}]);

答案 2 :(得分:0)

使用$ broadcase或$ emit事件,如:

app.controller('ctrl1', ['$scope', '$rootScope', function($scope, $rootScope) {
    $rootScope.$on("CustomEvent", function($event, data){
      alert(data);
    })
}]);

app.controller('ctrl2', ['$scope', function($scope) {
   $scope.$emit("CustomEvent", "SecondControllerValue");
}]);