【问题标题】:In angular.js, can a directive controller access data in a page controller that loaded it?在 angular.js 中,指令控制器可以访问加载它的页面控制器中的数据吗?
【发布时间】:2014-08-10 08:43:13
【问题描述】:

在 angular.js 中,指令控制器可以访问加载它的页面控制器中的数据吗?

/**
 * Profile directive
 */
    .directive('profile', function () {
        return {
            restrict: 'E',
            replace: true,
            templateUrl: '/partials/users/_profile.html',
            scope: {
                user: '=',
                show: '=?'
            },
            controller: function($scope, $rootScope){
                $scope.show = angular.isDefined($scope.show) ? $scope.show : { follow: true, link: true };
                $scope.currentUser = $rootScope.currentUser;

                //do stuff here and then set data in UserShowCtrl
            }
        };
    });

<profile user="user"></profile> 方法是从使用 UserShowCtrl 控制器的./users/show.html 调用的。

无论如何我可以在 profile 指令上使用范围和它自己的控制器,并且仍然能够将数据传递给 UserShowCtrl?

即使配置文件可以独立于它自己的功能,它仍然需要在 UserShowCtrl 控制器的页面级别设置一些数据。

这里是_user.html 加载<profile> 指令的地方。该页面的数据由UserShowCtrl 提供,并且有一些集合会在发生事情时更新,例如关注用户。

<ol class="following" ng-show="showConnections == 'following'">
    <li ng-repeat="following in user.following">
        <profile user="connections[following]"></profile>
    </li>
</ol>

现在 _profile.html 中有一个 ng-click="follow(user)"&gt;。我希望能够让指令处理这个问题,但也可以更新 UserShowCtrl 中的集合。

编辑:这是一个展示我正在尝试做的事情的 plunker:

http://plnkr.co/edit/9a5dxMVg9cKLptxnNfX3

【问题讨论】:

    标签: angularjs angularjs-scope angular-directive


    【解决方案1】:

    我不太确定你的目标是什么。

    您已经有 2 个双向数据绑定,这意味着如果您在指令中更改用户,这也将流向外部范围。

    所以你已经有一个解决方案摆在你面前...... 因此,如果这还不够“好”,那么您的问题中就缺少一些东西。

    这是一个插图:http://plnkr.co/edit/qEH2Pr1Pv7MTdXjHd4bD?p=preview

    但是,如果您在外部模板中使用创建子作用域的内容,将其绑定为“值”是不够的,您需要有一个 .在那里。

    但这就是问题所缺少的地方,如果你分享你的 show.html,我也许能够找到范围分解的地方并解释原因......


    demo.js 相关来源:

    app.directive('profile', function () {
            return {
                restrict: 'E',
                replace: true,
                template: '<div><input type="text" ng-model="user"></input></div>',
                scope: { //defines an isolate scope.
                    user: '=',
                    show: '=?'
                },
                controller: function($scope, $rootScope){
                    $scope.show = angular.isDefined($scope.show) ? $scope.show : { follow: true, link: true };
                    $scope.currentUser = $rootScope.currentUser;
    
                    $scope.user = "Changed by scope!";
                    //do stuff here and then set data in UserShowCtrl
                }
            };
        });
    
    app.controller('UserShowCtrl', function($scope) {
      $scope.value = "Value set outside!";
    
      $scope.alertValue = function() {
        alert($scope.value);
      }
    });
    

    来自home.html的相关来源:

    <div ng-controller="UserShowCtrl">
      {{ value }}
      <profile user="value"></profile>
      <button ng-click="alertValue()">ALERT!</button>
    </div>
    

    【讨论】:

    • 事实并非如此。一旦我在指令中定义了范围和控制器,与页面控制器的所有连接都将被切断。
    • 您已经创建了一个范围为 {} 的 Isolate Scope。但您对 Angular 说它应该为用户创建一个 2 路绑定以及一个可选的 2 路绑定用于显示。
    • 添加了更多信息以及一个示例,您可以在其中看到它的工作原理......
    • 我对那个 plunker 有点困惑,您似乎没有在任何地方使用 UserShowCtrl 或在任何地方包含 _user.html ...您是否有机会忘记保存最后一个一部分?
    • 这种情况下,如何从profile指令模板调用alertValue()函数?
    【解决方案2】:

    您可以使用 $scope.$parent.myvar 从指令中访问父范围。

    myvar 将在父作用域中解析,这意味着原型作用域继承用于解析变量。

    但是,这并不能保证 myvar 来自与 UserShowCtrl 相同的范围,因为 'profile' 指令和 UserShowCtrl 范围之间的任何范围都可能覆盖 'myvar'。

    更好的解决方案是使用指令到指令的通信。指令通信一般有两种方式:

    1. 通过传递给指令的属性。您已经使用此方法将“用户”和“显示”从父范围导入指令的隔离范围。

    2. 需要另一个指令。当你使用 'require: ^UserShow' 时,你指定你的 'profile' 指令需要另一个指令作为依赖。 '^' 表示它将在当前元素上搜索指令,或者在 DOM 树上更远的任何父元素上搜索。然后将 UserShow 的控制器传递给您的链接函数:

       .directive('UserShow', function () {
        return {
              restrict: 'E',
              controller: function($scope){
                    $scope.myvar = 'test';
                    this.setMyVar = function(var) {
                        $scope.myvar = var;
                    }
                  }
              };
          });
      
      .directive('profile', function () {
          return {
              restrict: 'E',
              replace: true,
              templateUrl: '/partials/users/_profile.html',
              require: '^UserShow',
              scope: {
                  user: '=',
                  show: '=?'
              },
              controller: function($scope, $rootScope){
              },
              link: function(scope, element, attr, UserShowCtrl) {
                  UserShowCtrl.setMyVar('hello world!);
              }
      
          };
      });
      

    HTML:

      <user-show>
           <profile>...</profile>
      </user-show>
    

    【讨论】:

      【解决方案3】:

      您需要使用服务才能在控制器、指令、服务之间共享任何信息

      类似

        angular.module('myapp',[]).
        service('myservice',function(){
            return {a:'A',b:'B'}
        }).
        controller('mycontroller',['myservice',function(myservice){
      
              //do someting with myservice    
      
        }]).
        directive('mydirective',['myservice',function(myservice){
      
              //do someting with myservice    
      
        }]);
      

      控制器和指令通过服务访问相同的数据

      【讨论】:

      • 我可以在mydirective 中更改myservice.a = 'aaaa';,它也会在mycontroller 中反映出来吗?
      • 是的,因为只要您执行 myservice.a,您就在服务参数上进行操作。您的更改将反映在服务中,然后对任何引用该服务的人可见
      猜你喜欢
      • 2015-05-13
      • 2017-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-03
      • 2015-07-29
      • 2016-03-26
      相关资源
      最近更新 更多