简体   繁体   English

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

[英]Controller Required By Directive Can't Be Found

I have a directive that I'd like another directive to be able to call in to. 我有一个指令,我想要另一个指令,以便能够调用。 I have been trying to use directive controllers to try to achieve this. 我一直在尝试使用指令控制器来尝试实现这一点。

Directive one would be sitting on the same page as directive two, and directive one would call methods exposed by directive two's controller: 指令1将与指令2位于同一页面上,指令1将调用指令2的控制器公开的方法:

Directive 1: 指令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();
                }
            }
        };
    });

Directive Two: 指令二:

'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
            }
        };
    });

File where the two are used and set up as siblings: 使用两者并将其设置为兄弟姐妹的文件:

<div>
    <div video-clip-details></div>
    <!-- main component for the file library -->
    <div file-library></div>
</div>

I know reading documentation I picked up that the controllers can be shared when the directives are on the same element, which makes me think I might be looking at this problem the wrong way. 我知道阅读文档,我知道当指令在同一个元素上时控制器可以共享,这让我觉得我可能会以错误的方式看待这个问题。 Can anyone put me on the right track? 谁能让我走上正轨?

From the angular.js documentation on directives 来自angular.js 文档的指令

When a directive uses require , $compile will throw an error unless the specified controller is found. 当指令使用require$compile将抛出错误,除非找到指定的控制器。 The ^ prefix means that this directive searches for the controller on its parents (without the ^ prefix, the directive would look for the controller on just its own element). ^前缀意味着该指令在其父节点上搜索控制器(没有^前缀,该指令将仅在其自己的元素上查找控制器)。

So basically what you are trying to do with having siblings directly communicate is not possible. 所以基本上你想要让兄弟姐妹直接沟通是不可能的。 I had run into this same issue but I did not want to use a service for communication. 我遇到了同样的问题,但我不想使用服务进行通信。 What I came up with was a method of using a parent directive to manage communication between its children, which are siblings. 我想出的是一种使用父指令来管理其子节点之间的通信的方法,这些子节点是兄弟节点。 I posted the example on github . 在github上发布了这个例子

What happens is that both children require the parent ( require: '^parentDirective' ) and their own controller, both of which are passed into the link function. 会发生什么是两个孩子都需要父( require: '^parentDirective' )和他们自己的控制器,这两个都传递给链接功能。 From there each child can get a reference to the parent controller and all of its public methods, as an API of sorts. 从那里,每个孩子都可以获得对父控制器及其所有公共方法的引用,作为各种API。

Below is one of the children itemEditor 下面是其中一个子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;
        }
    }
}

Note how the values passed into the require array are the parent directive's name and the current directive's name. 请注意传递给require数组的值是父指令的名称和当前指令的名称。 These are then both accessible in the link function via the controllers parameter. 然后可以通过controllers参数在link功能中访问它们。 Assign the parent directive's controller as a property of the current child's and then it can be accessed within the child's controller functions via that property. 将父指令的控制器指定为当前子控件的属性,然后可以通过该属性在子控制器函数中访问它。

Also notice how in the child directive's link function I call an initialize function from the child's controller. 还要注意在子指令的link函数中我如何从子控制器调用initialize函数。 This is where part of the communication lines are established. 这是通信线路的一部分建立的地方。

I'm basically saying, anytime you (parent directive) receive a request to edit an item, use this method of mine named editItem which takes an item as a parameter. 我基本上说,只要你(父指令)收到编辑项目的请求,就使用我的名为editItem方法,它将一个item作为参数。

Here is the parent directive 这是父指令

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;
        }
    }
}

Here in the parent you can see that the respondToEditsWith takes a method as a parameter and assigns that value to its editMethod property. 在父级中,您可以看到respondToEditsWith将方法作为参数,并将该值赋给其editMethod属性。 This property is called whenever the controller's editItem method is called and the item object is passed on to it, thus calling the child directive's editItem method. 只要调用控制器的editItem方法并将item对象传递给它,就会调用此属性,从而调用子指令的editItem方法。 Likewise, saving data works the same way in reverse. 同样,保存数据的工作方式相反。

Update : By the way, here is a blog post on coderwall.com where I got the original idea with good examples of require and controller options in directives. 更新 :顺便说一句,这是一篇关于coderwall.com的博客文章,在那里我得到了最初的想法,并在指令中提供了require和控制器选项的良好示例。 That said, his recommended syntax for the last example in that post did not work for me, which is why I created the example I reference above. 也就是说,他对该帖子中最后一个例子的推荐语法对我不起作用,这就是我创建上面引用的例子的原因。

There is no real way with require to communicate between sibling elements in the way you are trying to do here. 没有真正的方法要求以您在此处尝试的方式在兄弟元素之间进行通信。 The require works the way you have set up if the two directives are on the same element . 如果两个指令在同一个元素则require按照您设置的方式工作。

You can't do this however because both of your directives have an associated templateUrl that you want to use, and you can only have one per element. 但是,您不能这样做,因为您的两个指令都有一个您想要使用的关联templateUrl,并且每个元素只能有一个。

You could structure your html slightly differently to allow this to work though. 你可以稍微改变你的html结构以允许它工作。 You basically need to put one directive inside the other (transcluded) and use require: '^videoClipDetails' . 你基本上需要将一个指令放在另一个( require: '^videoClipDetails' )中并使用require: '^videoClipDetails' Meaning that it will look to the parent to find it. 这意味着它将寻找父母找到它。 I've set up a fiddle to demonstrate this: http://jsfiddle.net/WwCvQ/1/ 我已经设置了一个小提琴来证明这一点: http//jsfiddle.net/WwCvQ/1/

This is the code that makes the parent thing work: 这是使父项工作的代码:

// 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',

let me know if you have any questions! 如果您有任何疑问,请告诉我!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 无法找到指令&#39;...&#39;所需的控制器&#39;ngModel&#39; - Controller 'ngModel', required by directive '…', can't be found 找不到指令所需的AngularJS控制器 - AngularJS controller, required by directive, can't be found 无法找到指令'...'所需的控制器'ngModel' - Controller 'ngModel', required by directive '…', can't be found 找不到指令“ loginForm”所需的控制器“ alertForm”! 在angularjs中 - Controller 'alertForm', required by directive 'loginForm', can't be found! in angularjs 调节器 <directiveName> ,指令“ ngClass”要求,找不到 - Controller <directiveName>, Required by Directive 'ngClass', Can't be Found 无法找到指令&#39;ngSwitchWhen&#39;所需的AngularJS控制器&#39;ngSwitch&#39; - AngularJS Controller 'ngSwitch', required by directive 'ngSwitchWhen', can't be found 找不到指令“ ngInclude”所需的控制器“ uiTreeNodes” - Controller 'uiTreeNodes', required by directive 'ngInclude', can't be found 无法找到指令'ngMessage'所需的控制器'ngMessages' - Controller 'ngMessages', required by directive 'ngMessage', can't be found 找不到指令“ ngSwitch”所需的控制器“砌体” - Controller 'masonry', required by directive 'ngSwitch', can't be found 包装时找不到指令“ uibSlide”所需的控制器“ uibCarousel” - Controller 'uibCarousel', required by directive 'uibSlide', can't be found when wrapping
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM