Как требовать контроллер в директиве angularjs

Может ли кто-нибудь сказать мне, как включить контроллер из одной директивы в другую директиву angularJS. например, у меня есть следующий код

var app = angular.module('shop', []).
config(['$routeProvider', function ($routeProvider) {
    $routeProvider.when('/', {
        templateUrl: '/js/partials/home.html'
    })
        .when('/products', {
        controller: 'ProductsController',
        templateUrl: '/js/partials/products.html'
    })
        .when('/products/:productId', {
        controller: 'ProductController',
        templateUrl: '/js/partials/product.html'
    });
}]);

app.directive('mainCtrl', function () {
    return {
        controller: function ($scope) {}
    };
});

app.directive('addProduct', function () {
    return {
        restrict: 'C',
        require: '^mainCtrl',
        link: function (scope, lElement, attrs, mainCtrl) {
            //console.log(cartController);
        }
    };
});

По всем данным я должен иметь доступ к контроллеру в директиве addProduct, но я не уверен. Есть ли лучший способ сделать это?

Ответ 1

Мне повезло и ответили на это в комментарии к вопросу, но я полностью отвечаю за полноту, и поэтому мы можем отметить этот вопрос как "Ответ".


Это зависит от того, что вы хотите сделать, разделив контроллер; вы можете использовать один и тот же контроллер (хотя есть разные экземпляры), или вы можете использовать один и тот же экземпляр контроллера.

Поделиться контроллером

Две директивы могут использовать один и тот же контроллер, передавая один и тот же метод двум директивам, например:

app.controller( 'MyCtrl', function ( $scope ) {
  // do stuff...
});

app.directive( 'directiveOne', function () {
  return {
    controller: 'MyCtrl'
  };
});

app.directive( 'directiveTwo', function () {
  return {
    controller: 'MyCtrl'
  };
});

Каждая директива получит свой собственный экземпляр контроллера, но это позволяет вам делиться логикой между как можно большим количеством компонентов.

Требовать контроллер

Если вы хотите поделиться одним и тем же экземпляром контроллера, вы используете require.

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

^require, с добавлением каретки, проверяет элементы выше директивы в дополнение к текущему элементу, чтобы попытаться найти другую директиву. Это позволяет создавать сложные компоненты, где "подкомпоненты" могут прекрасно взаимодействовать с родительским компонентом через свой контроллер. Примеры могут включать вкладки, где каждая панель может связываться с общими вкладками для обработки переключения; набор аккордеона может гарантировать, что только один открыт одновременно; и др.

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

Обратитесь к странице руководства директив для получения дополнительной информации: http://docs.angularjs.org/guide/directive

Ответ 2

Существует хороший ответ на stackoverflow здесь Марк Райкок:

Управляющие контроллеры AngularJS, требующие контроллеров родительских директив

со ссылкой на этот очень понятный jsFiddle: http://jsfiddle.net/mrajcok/StXFK/

<div ng-controller="MyCtrl">
    <div screen>
        <div component>
            <div widget>
                <button ng-click="widgetIt()">Woo Hoo</button>
            </div>
        </div>
    </div>
</div>

JavaScript

var myApp = angular.module('myApp',[])

.directive('screen', function() {
    return {
        scope: true,
        controller: function() {
            this.doSomethingScreeny = function() {
                alert("screeny!");
            }
        }
    }
})

.directive('component', function() {
    return {
        scope: true,
        require: '^screen',
        controller: function($scope) {
            this.componentFunction = function() {
                $scope.screenCtrl.doSomethingScreeny();
            }
        },
        link: function(scope, element, attrs, screenCtrl) {
            scope.screenCtrl = screenCtrl
        }
    }
})

.directive('widget', function() {
    return {
        scope: true,
        require: "^component",
        link: function(scope, element, attrs, componentCtrl) {
            scope.widgetIt = function() {
                componentCtrl.componentFunction();
            };
        }
    }
})


//myApp.directive('myDirective', function() {});
//myApp.factory('myService', function() {});

function MyCtrl($scope) {
    $scope.name = 'Superhero';
}