【问题标题】:Directive accessing to parent controller function without $scope指令访问没有 $scope 的父控制器函数
【发布时间】:2015-04-08 13:47:39
【问题描述】:

所以我有这个指令,它有自己的范围,但我想访问其父控制器内的函数。如果父控制器使用 $scope.getElementsList() 公开函数,我可以这样做,尽管我试图避免使用 $scope,并且我有使用 self.getElementsList() 公开的函数并且指令无法访问它.

指令:

angular.module('myApp').directive('accountBalance', function() {
  return {
    scope: {
        elementId: '=elementid'
    },
    transclude: true,
    restrict: 'E',
    templateUrl: '../views_directives/account-balance.html',

    controller: function($scope) {
        $scope.removeElement = function(){
            //this where I want to access the parent function
            console.log($scope.$parent.getElementsList());
            console.log("ALSO I WANT TO ACCESS THIS DIRECTIVE elementId WITHOUT USING $scope", $scope.elementId);
        }
    }
  };
});

父控制器:

angular.module('myApp').controller('AppDesignCtrl', function ($scope) {
    var self = this;
    self.elementsList = [];
    self.getElementsList = function(){
        return self.elementsList;
    }

});

我还想知道在指令控制器内部访问传递给指令 $scope 的数据的最佳方式是什么。

scope: {
    elementId: '=elementid'
},

更新

<div>
   <i class="fa fa-arrows element-drag"></i>
   <i class="fa fa-trash-o element-remove" ng-click="removeElement()"></i>
</div>

那么从指令控制器内的指令模板调用函数呢?我需要用 $scope.removeElement() 之类的东西来公开它们吗?如何使用 this.removeElement() 并能够从模板中访问它?

抱歉这个问题太长了。自从我离开 Angular 一年多以来,我正在尝试为我的新项目设置最佳实践。

提前致谢

【问题讨论】:

  • 您使用的是哪个版本的 Angular?在 1.2 和 1.3 之间,情况发生了很大变化。
  • 你是如何使用你的指令的?
  • 我正在使用最新版本“版本”:“1.3.15”@NikosParaskevopoulos
  • @Satpal
  • 您真的需要在隔离范围内以两种方式绑定 id 吗?如果它作为属性访问,则父控制器范围将在指令中公开

标签: javascript angularjs


【解决方案1】:

(从下到上...)

要在不使用 Angular >= 1.2 中的范围的情况下调用控制器中的函数,请使用 controllerAs 语法:

<div ng-controller="AppDesignCtrl as appDesignCtrl">
    ...
    <i class="fa fa-trash-o element-remove" ng-click="appDesignCtrl.removeElement()"></i>
</div>

并且removeElement()必须是控制器的方法:

angular.module('myApp').controller('AppDesignCtrl', function ($scope) {
    ...
    this.removeElement = function() {
        ...
    };
});

要从 Angular >= 1.3 中的控制器访问范围数据,请使用新的 bindToController: true 配置(与新的 controllerAs 语法结合使用时特别有用):

angular.module('myApp').directive('accountBalance', function() {
    return {
        ...
        scope: {
            elementId: '=elementid'
        },
        controller: function() {
            // now elementId is a member of the controller:
            console.log(this.elementId);
        }
    };
});

说了这么多,如何从指令中调用getElementsList 的答案是:

angular.module('myApp').directive('accountBalance', function() {
    return {
        ...
        scope: {
            elementId: '=elementid',
            getElementList: '&'
        },
        controller: function() {
            ...
            // invoking the expression that was passed to us
            var theElements = this.getElementList();
        }
    };
});

正确的表达式应该传递为:

<div ng-controller="AppDesignCtrl as appDesignCtrl">
    <account-balance element-id="xxx"
        get-elements-list="appDesignCtrl.getElementsList()"></account-balance>
</div>

【讨论】:

  • 效果很好。我唯一的问题是关于从指令 html 模板到指令控制器的访问。指令的模板 URL: 到指令 angular.module('myApp') 的控制器。指令('accountBalance', function() { ... templateUrl: '../views_directives/account-balance.html', 控制器: function() { this.removeElement = function(){ ... } } }; } );由于该控制器没有名称,在这种情况下我该如何使用 controllerAs?
  • 我认为您需要 controllerAs 指令配置。在docs 中检查它,它作为{ restrict: 'E', ..., controller: function()..., controllerAs: 'ctrl', ...} 工作,然后控制器在指令的模板中作为ctrl 可用,例如要访问控制器的字段 foo,请在模板中写入 {{ ctrl.foo }}
【解决方案2】:

一般不推荐,因为指令是自包含的。如果您不打算重用该指令,这并不重要。明智地使用隔离作用域可以解决这个问题。

angular.module('myApp').directive('accountBalance', function() {
  return {
    scope: {
        outerScope: '@'
        elementId: '='
    },
    transclude: true,
    restrict: 'E',
    templateUrl: '../views_directives/account-balance.html',

    controller: function($scope) {
        console.log("we can use anything from other controller", $scope.outerScope.elementsList)
        $scope.elementId = "and share data with any other scope";
    }
  };
});

Controller定义为ng-controller="AppDesignCtrl as appDesign",指令用法为

<account-balance element-id="sharedParentScopeVar" outer-scope="appDesign">

因此,如果将指令移到其他控制器,则不会有任何问题。

我猜“最佳实践”可能是设置一个包含数据并由应用控制器和指令使用的服务,因此指令控制器对数据项而不是 DOM 元素进行操作。

从里面的指令模板调用函数呢 指令的控制者?我需要用 $scope.removeElement() 之类的东西?

你肯定不会。如果需要从外部使用函数,那么你做错了什么。如果它与 DOM 相关,则向相应元素发送消息以运行该函数。或者,如果是数据相关的,则将函数放入服务中。

【讨论】:

    猜你喜欢
    • 2014-07-09
    • 2015-06-28
    • 1970-01-01
    • 2016-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多