无法找到指令所需的控制器

bin*_*ant 23 angularjs angularjs-directive angularjs-scope

我有一个指令,我想要另一个指令,以便能够调用.我一直在尝试使用指令控制器来尝试实现这一点.

指令1将与指令2位于同一页面上,指令1将调用指令2的控制器公开的方法:

指令1:

'use strict';
angular.module('angularTestApp')
    .directive('fileLibrary', function () {
        return {
            templateUrl: 'views/manage/file_library/file-library.html',
            require: 'videoClipDetails',
            restrict: 'AE',
            link: function postLink(scope, element, attrs, videClipDetailsCtrl) {
                scope.doSomethingInVideoClipDirective = function() {
                    videClipDetailsCtrl.doSomething();
                }
            }
        };
    });
Run Code Online (Sandbox Code Playgroud)

指令二:

'use strict';
angular.module('angularTestApp')
    .directive('videoClipDetails', function () {
        return {
            templateUrl: 'views/video_clip/video-clip-details.html',
            restrict: 'AE',
            controller: function($scope, $element) {
                this.doSomething = function() {
                    console.log('I did something');
                }
            },
            link: function postLink(scope, element, attrs) {
                console.log('videoClipDetails directive');
                //start the element out as hidden
            }
        };
    });
Run Code Online (Sandbox Code Playgroud)

使用两者并将其设置为兄弟姐妹的文件:

<div>
    <div video-clip-details></div>
    <!-- main component for the file library -->
    <div file-library></div>
</div>
Run Code Online (Sandbox Code Playgroud)

我知道阅读文档,我知道当指令在同一个元素上时控制器可以共享,这让我觉得我可能会以错误的方式看待这个问题.谁能让我走上正轨?

sea*_*ght 16

来自angular.js 文档的指令

当指令使用时require,$compile除非找到指定的控制器,否则将抛出错误.该^前缀意味着该指令对于其父母则控制器搜索(不带^前缀,该指令看起来只是自己的元素上的控制器).

所以基本上你想要让兄弟姐妹直接沟通是不可能的.我遇到了同样的问题,但我不想使用服务进行通信.我想到的是一种使用父指令来管理其子节点之间的通信的方法,这些子节点是兄弟节点.我在github上发布了这个例子.

会发生什么是两个孩子都需要parent(require: '^parentDirective')和他们自己的控制器,这两个控制器都被传递到链接功能.从那里,每个孩子都可以获得对父控制器及其所有公共方法的引用,作为各种API.

下面是其中一个孩子 itemEditor

function itemEditor() {
    var directive = {
        link: link,
        scope: {},
        controller: controller,
        controllerAs: 'vm',
        require: ['^itemManager', 'itemEditor'],
        templateUrl: 'app/scripts/itemManager/itemManager.directives.itemEditor.html',
        restrict: 'A'
    };

    return directive;

    function link(scope, element, attrs, controllers) {
        var itemManagerController = controllers[0];
        var itemEditorController = controllers[1];

        itemEditorController.itemManager = itemManagerController;

        itemEditorController.initialize();
    }

    function controller() {
        var vm = this;

        // Properties
        vm.itemManager = {};
        vm.item = { id: -1, name: "", size: "" };

        // Methods
        vm.initialize = initialize;
        vm.updateItem = updateItem;
        vm.editItem = editItem;

        // Functions
        function initialize() {
            vm.itemManager.respondToEditsWith(vm.editItem);
        }

        function updateItem() {
            vm.itemManager.updateItem(vm.item);
            vm.item = {};
        }

        function editItem(item) {
            vm.item.id = item.id;
            vm.item.name = item.name;
            vm.item.size = item.size;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意传递给require数组的值是父指令的名称和当前指令的名称.然后可以link通过controllers参数在函数中访问它们.将父指令的控制器指定为当前子控件的属性,然后可以通过该属性在子控制器函数中访问它.

还要注意在child子指令的link函数中我如何initialize从子控制器中调用一个函数.这是通信线路的一部分建立的地方.

我基本上是说,无论何时你(父指令)都收到编辑项目的请求,请使用我的命名方法,该方法editItem将a item作为参数.

这是父指令

function itemManager() {
    var directive = {
        link: link,
        controller: controller,
        controllerAs: 'vm',
        templateUrl: 'app/scripts/itemManager/itemManager.directives.itemManager.html',
        restrict: 'A'
    };

    return directive;

    function link(scope, element, attrs, controller) {

    }

    function controller() {
        var vm = this;

        vm.updateMethod = null;
        vm.editMethod = null;

        vm.updateItem = updateItem;
        vm.editItem = editItem;
        vm.respondToUpdatesWith = respondToUpdatesWith;
        vm.respondToEditsWith = respondToEditsWith;

        function updateItem(item) {
            vm.updateMethod(item);
        }

        function editItem(item) {
            vm.editMethod(item);
        }

        function respondToUpdatesWith(method) {
            vm.updateMethod = method;
        }

        function respondToEditsWith(method) {
            vm.editMethod = method;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在父级中,您可以看到respondToEditsWith将方法作为参数并将该值赋给其editMethod属性.只要调用控制器的editItem方法并将item对象传递给它,就会调用此属性,从而调用子指令的editItem方法.同样,保存数据的工作方式相反.

更新:顺便说一句,这是一篇关于coderwall.com的博客文章,其中我require在指令中提供了很好的示例和控制器选项.也就是说,他对该帖子中最后一个例子的推荐语法对我不起作用,这就是我创建上面引用的例子的原因.


has*_*sin 7

没有真正的方法要求以您在此处尝试的方式在兄弟元素之间进行通信.如果两个指令在同一个元素,则require按照您设置的方式工作.

但是,您不能这样做,因为您的两个指令都有一个您想要使用的关联templateUrl,并且每个元素只能有一个.

你可以稍微改变你的html结构以允许它工作.你基本上需要将一个指令放在另一个指令(transcluded)中并使用require: '^videoClipDetails'.这意味着它将寻找父母找到它.我已经设置了一个小提琴来证明这一点:http://jsfiddle.net/WwCvQ/1/

这是使父项工作的代码:

// In videoClipDetails
template: '<div>clip details<div ng-transclude></div></div>',
transclude: 'true',
...
// in markup
<div video-clip-details> 
    <div file-library></div>
</div>
// in fileLibrary
require: '^videoClipDetails',
Run Code Online (Sandbox Code Playgroud)

如果您有任何疑问,请告诉我!