2015-08-07 7 views
3

У меня есть Угловое 1.3 модуль, который выглядит примерно так (директива, которая требует наличия родительской директивы, используя controllerAs):Как получить доступ к контроллеру require'd с другого контроллера?

angular.module('fooModule', []) 

.controller('FooController', function ($scope) { 
    this.doSomething = function() { 
    // Accessing parentDirectiveCtrl via $scope 
    $scope.parentDirectiveCtrl(); 
    }; 
}) 

.directive('fooDirective', function() { 
    return { 
    // Passing in parentDirectiveCtrl into $scope here 
    link: function link(scope, element, attrs, parentDirectiveCtrl) { 
     scope.parentDirectiveCtrl = parentDirectiveCtrl; 
    }, 
    controller: 'FooController', 
    controllerAs: 'controller', 
    bindToController: true, 
    require: '^parentDirective' 
    }; 
}); 

Здесь я только с помощью $scope пройти через parentDirectiveCtrl, что кажется немного неуклюжий.

Есть ли другой способ доступа к контроллеру require от контроллера директивы без функции связывания?

+2

Вы не должны передать его через рамки - вы можете просто присвоить его ваш собственный контроллер ... но в остальном, да - вам нужна функция связи –

+0

Как вы это понимаете, назначив ее? – thatmarvin

+0

Вам нужен как ваш собственный контроллер, так и родительский ... 'require: [" fooDirective ","^parentDirective "]' ... и присваивать один другому ... но для него все равно потребуется функция ссылки - которая где вводятся требуемые контроллеры. –

ответ

3

Вы должны использовать функцию link для получения контроллеров require, но вам не нужно использовать область действия, чтобы передать ссылку на контроллер самостоятельно. Вместо этого, передать ее непосредственно на свой собственный контроллер:

.directive('fooDirective', function() { 
    return { 

    require: ["fooDirective", "^parentDirective"], 

    link: function link(scope, element, attrs, ctrls) { 
     var me  = ctrls[0], 
      parent = ctrls[1]; 

     me.parent = parent; 
    }, 
    controller: function(){...}, 
    }; 
}); 

Будьте осторожны, так как контроллер работает до ссылки, так что в контроллер this.parent не undefined, пока после запуска функции связи. Если вам нужно точно знать, когда это произойдет, вы всегда можете использовать функцию контроллера передать parentDirective контроллер для:

link: function link(scope, element, attrs, ctrls) { 
    //... 

    me.registerParent(parent); 
}, 
controller: function(){ 
    this.registerParent = function(parent){ 
    //... 
    } 
} 
1

Существует способ избежать использования $scope для доступа родительского контроллера, но вы должны использовать link функция. документация ANGULAR в says:

Требовать

Требовать другую директиву и ввести свой контроллер в качестве четвертого аргумента функции связующей ...

Вариант 1

С controllerAs creat es в scope вашего контроллера, вы можете получить доступ к этому пространству имен внутри своей функции link и поставить контроллер на контроллер childDirective вместо $scope. Тогда код будет выглядеть так.

angular.module('app', []). 
    controller('parentController', function() { 
    this.doSomething = function() { 
     alert('parent'); 
    }; 
    }). 
    controller('childController', function() { 
    this.click = function() { 
     this.parentDirectiveCtrl.doSomething(); 
    } 
    }). 
    directive('parentDirective', function() { 
    return { 
     controller: 'parentController' 
    } 
    }). 
    directive('childDirective', function() { 
    return { 
     template: '<button ng-click="controller.click()">Click me</button>', 
     link: function link(scope, element, attrs, parentDirectiveCtrl) { 
     scope.controller.parentDirectiveCtrl = parentDirectiveCtrl; 
     }, 
     controller: 'childController', 
     controllerAs: 'controller', 
     bindToController: true, 
     require: '^parentDirective' 
    } 
    }); 

Plunker:

http://plnkr.co/edit/YwakJATaeuvUV2RBDTGr?p=preview

Вариант 2

Я обычно не используют контроллеры в своих директивах на всех и поделиться функциональность с помощью услуг. Если вам не нужно взаимодействовать с изолированными областями родительских и дочерних директив, просто добавьте одну и ту же услугу к обоим из них и включите все функциональные возможности для обслуживания.

angular.module('app', []). 
    service('srv', function() { 
    this.value = ''; 
    this.doSomething = function(source) { 
     this.value = source; 
    } 
    }). 
    directive('parentDirective', ['srv', function(srv) { 
    return { 
     template: '<div>' + 
        '<span ng-click="srv.doSomething(\'parent\')">Parent {{srv.value}}</span>' + 
        '<span ng-transclude></span>' + 
       '</div>', 
     transclude: true, 
     link: function(scope) { scope.srv = srv; } 
    }; 
    }]). 
    directive('childDirective', ['srv', function(srv) { 
    return { 
     template: '<button ng-click="srv.doSomething(\'child\')">Click me</button>', 
     link: function link(scope) { scope.srv = srv; } 
    } 
    }]); 

Plunker

http://plnkr.co/edit/R4zrXz2DBzyOuhugRU5U?p=preview

+0

Я попробовал и понял, что это не сработает, когда есть несколько экземпляров директив, потому что сервисы - это синглтоны. – thatmarvin

0

Хороший вопрос! Угловой позволяет передавать «родительский» контроллер. У вас уже есть параметр в вашей функции ссылок. Это четвертый параметр. Я назвал его ctrl для простоты. Вам не нужна строка scope.parentDirectiveCtrl = parentDirectiveCtrl, которая у вас есть.

.directive('fooDirective', function() { 
    return { 
// Passing in parentDirectiveCtrl into $scope here 
link: function link(scope, element, attrs, ctrl) { 
    // What you had here is not required. 
}, 
controller: 'FooController', 
controllerAs: 'controller', 
bindToController: true, 
require: '^parentDirective'};}); 

Теперь на вашем родительском контроллере у вас есть

this.doSomething=function(). 

Вы можете получить доступ к этой DoSomething в

ctrl.doSomething().