在AngularJs中从父指令调用子指令函数

7
如何在父指令的按钮点击监听器中调用子指令定义的方法。
angular.module('editableDivDirective', [])

.directive("editableDiv", function() {
    var directive = {};
    directive.restrict = 'E';
    directive.replace = 'true';
    directive.scope = {};
    directive.transclude = 'true';
    directive.template =
        '<div id="wrapper">' +
            '<div required class="text-area" name="search" contenteditable="true" ng-model="formData.text"></div>' +
            '<button type="submit" class="btn btn-warning add-button" id="submit" ng-click="createTodo()">Add</button>' +
        '</div>';
    directive.link = function(scope, element, attrs, controller) {
        scope.createTodo = function(){
            // do something         
            // Call child directive setPlaceholderText()
        }
    };

    return directive;
})
.directive("contenteditable", function() {
    var directive = {};
    directive.require = ['^editableDiv','?ngModel'];
    directive.restrict = 'A';
    directive.scope = {};
    directive.link = function(scope, element, attrs, ctrls) {
        var ngModel = ctrls[1];
        var editableDivController = ctrls[0];

         function setPlaceholderText(){
            return element.html("Hello World");
        }

    return directive;
})

我想在父指令调用'scope.createTodo()'时调用子指令setPlaceholderText()。
有什么办法可以实现?

你的具体用例是什么?你已经尝试过什么? - Patrick
@Patrick,我已经添加了更多细节。抱歉离开电脑一段时间,没能及时添加。 - jsbisht
3个回答

3
在您的父指令中。
link: function($scope,$el,$attr) {
    $el.find(".thing").on('click',function(event){
       $scope.$broadcast('thing', $scope.someData);
    });
}

在您的子指令中
link: function($scope. $el, $attr) {
    $scope.$on('thing',function(event, someData) {
       alert('My parent called me with this data: ' + someData);
    });
}

1
谢谢 Mathew。当指令具有隔离作用域时,这是否适用? - jsbisht

2
你可以将事件广播到子作用域(如上所述),或者还可以从子指令向父指令的控制器中添加函数。
这里有一个 jsfiddle,其中包含广播到子指令和使用控制器技术的示例。
angular.module("myApp", [])

.directive("parentDirective", function () {
    var directive = {};
    directive.restrict = "E";
    directive.scope = {};
    directive.template = '<div>' +
        '<button type="button" ng-click="broadcastDemo()">' +
            'Broadcast to child' +
        '</button>' +
        '<button type="button" ng-click="controllerDemo()">' +
            'Use Controller' +
        '</button><br /><br />' +
        '<child-directive></child-directive>';
    //Setup directive controller
    directive.controller = function ($scope) {
        var ctrl = this;
        //Store events for convenience
        var events = ctrl.events = {
            setPlaceHolderText: "setPlaceHolderTextEvent"
        };

        $scope.broadcastDemo = function () {
            //$broadcast event and optional additional args
            $scope.$broadcast(events.setPlaceHolderText, "Additional arg1", "Additional arg2");
        };

        $scope.controllerDemo = function () {
            //do some work

            //call the ctrl.setPlaceHolderText added by child
            if (ctrl.setPlaceHolderText) {
                ctrl.setPlaceHolderText();
            }
        };
    };
    return directive;
})

.directive("childDirective", function () {
    var directive = {};
    directive.restrict = "E";
    directive.scope = {};
    directive.require = ["^parentDirective", "?ngModel"];
    directive.template = '<div></div>';
    directive.link = function (scope, elem, attrs, ctrl) {
        var parentDirCtrl = ctrl[0];
        //allow parent scope(s) to $broadcast event
        scope.$on(parentDirCtrl.events.setPlaceHolderText,
            function (event, arg1, arg2) {
                elem.html("$Broadcast: " + arg1 + " " + arg2);
            });

        //Add function to parent controller
        parentDirCtrl.setPlaceHolderText = function () {
            elem.html("Added to parent controller!");
        }
    };

    return directive;
});

如果您有多个 childDirectives,并且选择将函数添加到 parent directive 控制器中,则必须小心,因为每个额外的 child directive 都会覆盖 ctrl.setPlaceHolderText(即只调用一个 elem.html)。 bindonce 库使用类似第二种技术的方法,允许 child directives 向 parent directive 添加“绑定器”。事件模型可能更适合您的目的,但我想提供另一种指令通信的选项。

0

广播不是首选,因为如果有多个子实例甚至父子组合,则广播将触发所有内容。


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