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

时间:2014-12-18 19:05:07

标签: angularjs angularjs-directive angularjs-scope

如何在父指令的按钮单击侦听器中调用child指令中定义的方法。

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

我想在调用parent指令的“scope.createTodo()”时调用child指令setPlaceholderText()。

如何做到这一点。

3 个答案:

答案 0 :(得分: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 :(得分:2)

您可以将$事件广播到子范围(如上所述),或者您也可以从子指令向父指令的控制器添加一个函数。

这是一个jsfiddle,其中包含$ broadcast to child指令和使用控制器技术的示例。

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并且您要将功能添加到父指令控制器,则必须采取预防措施,因为每个额外的子指令都会破坏ctrl.setPlaceHolderText(即只调用一个elem.html)。

bindonce库使用类似于第二种技术的东西,允许子指令将“绑定器”添加到父指令。事件模型可能更适合您的目的,但希望为指令通信提供另一种选择。

答案 2 :(得分:0)

广播不是首选,因为如果有多个子实例甚至父子组合,那么广播将触发全部。

相关问题