如何在AngularJS中的两个指令之间共享作用域?

17

我想在以下两个指令之间共享$scope

One23SRCApp.directive('directive1',function() {
    return {
        restrict: "A",
        scope:true,
        link: function (scope, element, attrs) {
           scope.tablename = "table";
        }
    };
});


One23SRCApp.directive('directive2',function() {
    return {
        restrict: "A",
           link: function (scope, element, attrs) {
           var tablename = scope.tablename;
        }
    };
})
在HTML中,我有:

<input type="text" directive2 placeholder="Search Models..."> 

<table directive1>
  <tr>
     <td>column1</td>
     <td>column1</td>
   </tr>
</table>

我已经创建了名为"directive1"的指令,使用隔离作用域,并将名称"table"分配给scope.tablename属性。但我无法在另一个指令中访问此作用域属性。

那么,我如何在一个指令中访问另一个指令的作用域?


HTML中指令是如何组织的? - Chandermani
@chnadermani,我已经更新了我的问题,我在不同的元素上应用了指令。 - Shivkumar
4个回答

21

AngularJS支持指令控制器,这是在多个需要相同控制器的指令之间共享控制器。这使得您可以在任何需要该控制器的指令中访问和修改tableConfig,而无需声明单独的服务或事件。有关更多信息,请参阅指令文档中的“创建通信指令”

例如,这就是ngModelngForm的工作原理。


很好,我完全错过了那个选项。 - Erik Honn
1
在那里找不到有关“控制器构造函数”的任何内容了。但也许你指的是“创建指令进行通信”部分? - Mattias Nordqvist
你说得对,文档已经更改,我正在更新答案。谢谢! - Steve Klösters

16

我的建议是使用共享资源,比如服务。服务是单例的,这意味着每个服务只有一个实例,因此您可以使用它们在指令、控制器、作用域甚至在通过路由更改页面时共享数据。

您可以像这样定义资源服务:

app.factory("MyResource",function(){
    return {};
});

然后,您可以将该服务注入到指令中(如果需要,也可以注入到控制器中),并像这样使用它。

One23SRCApp.directive('directive1', ['MyResource', function(MyResource) {
    return {
        restrict: "A",
        scope:true,
        link: function (scope, element, attrs) {
           var resource = MyResource;
           resource.name = 'Foo';
        }
    };
});
One23SRCApp.directive('directive2', ['MyResource', function(MyResource) {
    return {
        restrict: "A",
        link: function (scope, element, attrs) {
           var resource = MyResource;
           console.log(resource.name);
        }
    };
});

指令2将记录“Foo”,因为资源是共享的。但请确保您按正确顺序运行指令!

**

您还可以从每个指令中进行双向数据绑定到父作用域(请参见Chandermani答案),但上述方法是一种非常有用且强大的方式,可以在不必广播或跟踪HTML中确切位置的情况下获取所需的数据。

编辑: 尽管我没有尝试过,但上述内容在控制器和路由之间共享信息时非常有用,请查看stevuu回答。它似乎更适合指令。


5

您可以在需要跨指令同步的项目上执行$rootScope.$broadcast

或者,您可以将对象传递给指令1隔离作用域,它将充当通信机制。如果您更改该对象的子属性,例如tablename,则会影响父级作用域。

类似于

One23SRCApp.directive('directive1',function() {
    return {
        restrict: "A",
        scope:{tableconfig:'='},
        link: function (scope, element, attrs) {
           scope.tableconfig.tablename= "table";
        }
    };
});


One23SRCApp.directive('directive2',function() {
    return {
        restrict: "A",
           link: function (scope, element, attrs) {
           var tablename = scope.tableconfig.tablename;
        }
    };
})

HTML代码变成了:

<table directive1 tableconfig='tableconfig'>
  <tr>
     <td>column1</td>
   <td>column1</td>
   </tr>
</table>

您的控制器应该定义这个对象:

$scope.tableconfig={};

该对象用于配置表格的相关参数。

13
使用$rootScope是一种反模式。 - Willem D'Haeseleer
这是一种不好的做法,如果你只想在指令之间共享相同的作用域,那么你的隔离作用域就会被污染。 - Joris Brauns
@Chandermani。我遇到了一个非常棘手的问题,与Angular有关。你能看一下这个链接吗?http://stackoverflow.com/questions/43521905/set-one-showrangeselector-for-two-dygraph 谢谢。 - Varun Sharma

4

Chandermani的示例正在运行。然而,这样做仍需要在指令上分配属性,并且不再是隔离的。这会污染作用域...

我的建议是使用控制器共享您的隔离作用域并通过这种方式传递它。 你的房子,你的代码!在编码之前先思考,但最重要的是...享受!

One23SRCApp.directive('directive1',function() {
    return {
         restrict: "A",
         scope: true,
         controller : function($scope){
              $scope.tableconfig= {};
              this.config = function (){ 
                   return $scope.tableconfig;
              }
         },
         link: function (scope, element, attrs) {
             scope.tableconfig.tablename= "table";
         }
    }
});


One23SRCApp.directive('directive2',function() {
     return {
           restrict: "A",
           //^ -- Look for the controller on parent elements, not just on the local scope
           //? -- Don't raise an error if the controller isn't found
           require: "^directive1",
           link: function (scope, element, attrs) {
               var tablename = scope.config().tablename;
           }
    }
});

用法

<!-- Notice, no need to share a scope as attribute -->
<div directive1>
    <div directive2>
    </div>
</div>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接