AngularJS: как вызвать функцию дочернего объекта в родительском пространстве

Как вызвать метод, определенный в области дочерних объектов, из его родительской области?

function ParentCntl() {
    // I want to call the $scope.get here
}

function ChildCntl($scope) {
    $scope.get = function() {
        return "LOL";    
    }
}

http://jsfiddle.net/wUPdW/

Ответ 1

Вы можете использовать $broadcast от родителя к дочернему:

function ParentCntl($scope) {

    $scope.msg = "";
    $scope.get = function(){
        $scope.$broadcast ('someEvent');
        return  $scope.msg;        
    }
}

function ChildCntl($scope) {               
    $scope.$on('someEvent', function(e) {  
        $scope.$parent.msg = $scope.get();            
    });

    $scope.get = function(){
        return "LOL";    
    }
}

Рабочая скрипка: http://jsfiddle.net/wUPdW/2/

UPDATE. Существует еще одна версия, менее связанная и более проверяемая:

function ParentCntl($scope) {
    $scope.msg = "";
    $scope.get = function(){
        $scope.$broadcast ('someEvent');
        return  $scope.msg;        
    }

    $scope.$on('pingBack', function(e,data) {  
        $scope.msg = data;        
    });
}

function ChildCntl($scope) {               
    $scope.$on('someEvent', function(e) {  
        $scope.$emit("pingBack", $scope.get());        
    });

    $scope.get = function(){
        return "LOL";    
    }
}

Fiddle: http://jsfiddle.net/uypo360u/

Ответ 2

Позвольте мне предложить другое решение:

var app = angular.module("myNoteApp", []);


app.controller("ParentCntl", function($scope) {
    $scope.obj = {};
});

app.controller("ChildCntl", function($scope) {
    $scope.obj.get = function() {
            return "LOL";    
    };
});

Меньше кода и использование прототипического наследования.

Plunk

Ответ 3

Зарегистрируйте дочернюю функцию родителя, когда ребенок инициализируется. Я использовал "как" для ясности в шаблоне.

TEMPLATE

<div ng-controller="ParentCntl as p">
  <div ng-controller="ChildCntl as c" ng-init="p.init(c.get)"></div>
</div>

КОНТРОЛЛЕРЫ

...
function ParentCntl() {
  var p = this;
  p.init = function(fnToRegister) {
    p.childGet = fnToRegister;
  };
 // call p.childGet when you want
}

function ChildCntl() {
  var c = this;
  c.get = function() {
    return "LOL";    
  };
}

"Но", вы говорите: "ng-init не предполагается использовать таким образом!". Ну, да, но

  • что документация не объясняет, почему нет, и
  • Я не считаю, что авторы документации рассматривали ВСЕ возможные варианты использования.

Я говорю, что это хорошо для этого. Если вы хотите сфокусировать меня, прокомментируйте причины!:)

Мне нравится этот подход, потому что он сохраняет компоненты более модульными. Единственные привязки находятся в шаблоне и означают, что

  • дочерний контроллер не должен знать ничего о том, какой объект добавить свою функцию (как в ответе @canttouchit)
  • родительский элемент управления может использоваться с любым другим дочерним элементом управления, который имеет функцию get
  • не требует широковещательной передачи, которая будет очень уродливой в большом приложении, если вы не будете строго контролировать пространство имен событий

Этот подход более приближен к Идея теро модуляции с директивами (обратите внимание, что в его модульном примере contestants передается из родительской в "дочернюю" директиву IN THE ОБРАЗЕЦ).

Действительно, другим решением может быть рассмотрение реализации ChildCntl в качестве директивы и использование привязки & для регистрации метода init.