angularjs 지시문에서 컨트롤러를 요구하는 방법


86

누구든지 한 지시문의 컨트롤러를 다른 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 지시문에서 컨트롤러에 액세스 할 수 있어야하지만 그렇지 않습니다. 이 작업을 수행하는 더 좋은 방법이 있습니까?


5
require다른 지시문이 있는지 확인한 다음 해당 컨트롤러를 포함합니다. ^require현재 요소 외에도 현재 요소 위에있는 요소를 확인합니다. 따라서 이것이 작동하려면 두 지시문을 함께 사용해야합니다. 그렇지 않으면 컨트롤러를 정의한 app.controller다음 두 지시문에서 사용하십시오. 어느 쪽이든, 이것을 HTML 코드와 함께 간단한 Plunker에 넣을 수 있습니까?
Josh David Miller

답변:


187

나는 운이 좋았고 질문에 대한 댓글로 이에 답했지만 완전성을 위해 전체 답변을 게시하고 있으므로이 질문을 "답변 됨"으로 표시 할 수 있습니다.


컨트롤러를 공유하여 수행하려는 작업에 따라 다릅니다. 동일한 컨트롤러 (인스턴스가 다르더라도)를 공유하거나 동일한 컨트롤러 인스턴스를 공유 할 수 있습니다.

컨트롤러 공유

두 지시문은 다음과 같이 두 지시문에 동일한 메서드를 전달하여 동일한 컨트롤러를 사용할 수 있습니다.

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


4
형제 지시어 컨트롤러를 요구할 수 있습니까? 기본적으로 ng-repeat를 사용하여 반복되는 형제 지시문 (동일한 DOM 요소가 아닌 DOM 형제에서와 같이)간에 컨트롤러 또는 서비스의 동일한 인스턴스를 공유해야합니다. 반복되는 각 항목에 공유 상태 또는 논리가 필요한 지시문이 있다고 상상해보십시오.
CMCDragonkai

2
@CMCDragonkai 그렇게 할 수있는 방법은 없지만 동일한 작업을 수행하는 두 가지 일반적인 방법이 있습니다. 첫 번째는 형제가 모두 동일한 "유형"인 경우 ngRepeat 위의 요소는 컨테이너 지시문과 같을 수 있으며 모든 하위 요소는 대신 해당 지시문을 요구할 수 있으며 모두 동일한 컨트롤러를 공유합니다. 보다 일반적인 솔루션 (종종 더 정식)은 공유 서비스를 사용하는 것입니다. 이 형제 자매들이 무엇을하고 무엇을 공유해야하는지 자세히 설명해 주시겠습니까?
Josh David Miller

네, 결국 첫 번째 옵션을 수행했습니다. 컨테이너 지시어 컨트롤러 사용. 잘 작동합니다. 그것은 Masonry를위한 것입니다.
CMCDragonkai

이것은 훌륭한 대답이며이 모든 것이 어떻게 작동하는지에 대한 이해를 굳혔습니다. 감사! (참고로 이것은 새로운 기능 일 수 있지만 require단일 지시문 또는 지시문 배열을 지정하는 데 사용할 수 있습니다. 각 지시문은 ^보다 세부적인 요구 사항을 위해 캐럿 ( ) 접두사를 붙일 수 있습니다 .)
jedd.ahyoung

두 지시문에서 동일한 컨트롤러를 사용하면 각 지시문에 고유 한 인스턴스가 제공되지 않습니다.
jsbisht

27

Mark Rajcok의 좋은 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>

자바 스크립트

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

4
저에게 Mark Rajcok의 예제 클릭을 가장 많이 만든 것은 컨트롤러 메서드가 생성되는 방식에주의를 기울이는 것이 었습니다. 일반적으로 $ scope.methodName = function () {...}을 통해 생성 된 컨트롤러 메서드를 볼 수 있지만 이것이 작동하려면 액세스하려는 메서드에 this.methodName을 사용해야합니다. 처음에는 알아 차리지 못했습니다.
coblr 2014 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.