web-dev-qa-db-fra.com

Comment exiger un contrôleur dans une directive angularjs

Quelqu'un peut-il me dire comment inclure un contrôleur d'une directive dans une autre directive angularJS. par exemple j'ai le code suivant

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

De manière générale, je devrais pouvoir accéder au contrôleur dans la directive addProduct, mais je ne le suis pas. Existe-t-il une meilleure façon de le faire?

83
Edgar Martinez

J'ai eu de la chance et j'ai répondu à cela dans un commentaire sur la question, mais je poste une réponse complète dans un souci d'exhaustivité et nous pouvons donc marquer cette question comme "Répondu".


Cela dépend de ce que vous voulez accomplir en partageant un contrôleur. vous pouvez partager le même contrôleur (bien que différentes instances) ou la même instance de contrôleur.

Partager un contrôleur

Deux directives peuvent utiliser le même contrôleur en transmettant la même méthode à deux directives, comme suit:

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

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

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

Chaque directive obtiendra sa propre instance du contrôleur, mais cela vous permet de partager la logique entre autant de composants que vous le souhaitez.

Nécessite un contrôleur

Si vous voulez partager la même instance d'un contrôleur, utilisez require.

require assure la présence d'une autre directive, puis inclut son contrôleur en tant que paramètre de la fonction de liaison. Ainsi, si vous avez deux directives sur un élément, votre directive peut exiger la présence de l'autre directive et accéder à ses méthodes de contrôleur. Un cas d'utilisation courant pour cela est d'exiger ngModel.

^require, avec l'ajout du curseur, vérifie les éléments supérieurs à la directive, en plus de l'élément actuel, pour tenter de trouver l'autre directive. Cela vous permet de créer des composants complexes dans lesquels les "sous-composants" peuvent communiquer avec le composant parent par le biais de son contrôleur. Les exemples peuvent inclure des onglets, où chaque volet peut communiquer avec les onglets globaux pour gérer le basculement; un ensemble accordéon pourrait assurer qu'un seul est ouvert à la fois; etc.

Dans les deux cas, vous devez utiliser les deux directives ensemble pour que cela fonctionne. require est un moyen de communiquer entre composants.

Consultez la page Guide des directives pour plus d’informations: http://docs.angularjs.org/guide/directive

183
Josh David Miller

Il y a une bonne réponse de stackoverflow ici par Mark Rajcok:

Contrôleurs de directive AngularJS nécessitant des contrôleurs de directive parent?

avec un lien vers ce très clair 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';
}
27
Joseph Oster