0

我有一个 AngularJS 应用程序,在其中一个页面上,我有许多小部件,每个小部件都显示有关系统一部分状态的一些信息。我目前正在添加功能以允许用户“隐藏”给定小部件的标题。

在显示小部件的页面上有一个“设置”按钮,单击该按钮时,会在每个小部件顶部覆盖一个工具栏。工具栏有许多按钮——其中一个是另一个“设置”按钮,它打开一个对话框,允许用户更改该特定小部件的设置。

我在对话框中添加了一个复选框,以使用户能够从视图中“隐藏”该特定小部件的标题:

配置项目对话框

当在对话框中选中复选框并且用户单击“预览”时,我期望(最终 - 我仍在努力实现该功能)隐藏该特定小部件的标题。但是,目前,当用户单击“预览”时,无论是否选中该复选框,我都会在控制台中收到一条错误消息:

类型错误:$scope.widget.toggleWidgetHeading 不是函数

此错误来自$scope.preview在对话框中单击“预览”按钮时调用的 ctrl.js 中的函数:

}).controller('WidgetPickerCtrl', function($scope, $timeout, fxTag, gPresets, appWidget) {
    ...
    $scope.preview = function(e) {
        $scope.widget.toggleWidgetHeading();
        ...
    };
    ...
});

我不明白为什么我会收到这个控制台错误,因为toggleWidgetHeading()显然是一个函数......

如果我在 Sublime 中右键单击上面的函数调用,然后选择“转到定义”,我将被带到定义函数的 directive.js 文件:

.directive('appWidget', function($timeout, fxTag, appColorFilter) {
    return {
        ...
        link: function($scope, $element){
            ...
            var toggleWidgetHeading = function(){
                ...
            }
            ...
        }
    }
})

此外,单击对话框上的“预览”按钮不再关闭对话框...

为什么当它被明确定义为一个函数时,我被告知这个函数调用不是一个函数?这里的问题是否与范围有关(即我从 ctrl.js 调用该函数,即使它是在directive.js 中定义的)?

4

1 回答 1

0

您添加的指令的定义...实际上是关于指令范围的真正相关部分。

指令可以实现多种范围。您实际上可以继承和访问父范围,或者您可以拥有一个独立的范围。您可以在官方文档中阅读到相关内容,其中有很好的解释:

https://docs.angularjs.org/guide/directive

然而,无论你使用什么范围,默认情况下 AngularJS 都实现了范围的继承,就像继承通常工作的那样:子级可以访问父级方法,但父级不能访问子级的方法。

在这里,您似乎试图从父范围(控制器)访问指令的范围,这实际上是不可能的。(即使在链接函数中您将其定义toggleWidgetHeading为私有变量,并且与$scope自身无关 - 但它也不起作用)。

所以在这些情况下你几乎没有选择:

  1. 在服务中定义您的“可见属性”并将服务注入指令和控制器中。然后使用服务来访问和更改这些值,以便它们在控制器和指令之间同步
  2. 将范围参数作为回调添加到指令中,&并从控制器提供一个函数,该函数返回所选小部件的可见性,因此您可以从指令中调用该函数并取回小部件可见性的值
  3. 在指令中添加一个范围参数作为双向数据绑定=,它绑定到小部件对控制器的可见性,以便您始终在控制器和指令之间保持同步
  4. 用于events在控制器和指令之间进行通信,在可见性更改时从控制器广播事件,并从指令中读取事件以获取小部件的可见性值

我希望这是有道理的

于 2017-08-21T10:31:59.103 回答